Aptos Agent Skills (https://github.com/aptos-labs/aptos-agent-skills) cover common workflows: write-contracts, generate-tests, security-audit, deploy-contracts, use-ts-sdk, ts-sdk-transactions, create-aptos-project, analyze-gas-optimization, modernize-move. Install the skill that matches the task before deep work. This is the curated low-token Aptos developer documentation set for AI agents and IDE assistants. # Build the Future of Web3 on Aptos > Everything you need to build a best-in-class Web3 experience. Getting Started * [Deploy Your First Move Smart Contract](/build/guides/first-move-module) Compile & publish Move modules to devnet in minutes. * [Your First Transaction](/build/guides/first-transaction) Write and read on-chain data using the TypeScript SDK. * [Code with AI (MCP)](/build/ai/aptos-mcp) Give Cursor and Claude Code direct access to Aptos APIs. * [NEW! Agent Skills](/build/ai/aptos-agent-skills) Move and TS SDK skills for Claude Code, Cursor, Copilot. Tools * [NEW! AskAptos AI Chatbot](/build/ai) Query docs, plan or refine requirements with AI (top right!). * [Testnet Faucet](/network/faucet) Fund your testnet account with APT to start building. * [Official SDKs](/build/sdks) TypeScript, Go, Java, Python, Rust, C++, Unity, and more. * [Aptos CLI](/build/cli) Compile, test, publish contracts; accounts & keys; localnet. Smart Contracts * [NEW! Move on Aptos (VS Code Extension)](/build/smart-contracts/move-vscode-extension) Aptos Labs’ official extension for Move development. * [Objects](/build/smart-contracts/objects) Composable on-chain primitives for flexible asset ownership, addressing, & programmability. * [The Move Book](https://aptos-labs.github.io/move-book/) Understand Move syntax, types, resources, & best practices. * [Vibe Code a full-stack dApp on Learn](https://learn.aptoslabs.com/en/hackathon/vibe-coder-to-aptos-guide/introduction) Interactive AI workshop to quickly build a full-stack dApp. On-Chain Features * [Sponsored Transactions](/build/guides/sponsored-transactions) Pay for users’ gas so they can use your dApp with zero APT. * [Keyless Accounts](/build/guides/aptos-keyless) Onboard users and sign without wallets or seed phrases. * [NEW! Orderless Transactions](/build/guides/orderless-transactions) High-volume apps can be safer by sending transactions out of order with replay-protection nonce. * [On-chain Randomness](/build/smart-contracts/randomness) Verifiable random number = fair games, lotteries, & drops. Resources * [NEW! LLMs.txt Integration](/llms-txt) AI-optimized documentation format, paste it in your favorite large context AI and get moving! * [Query, Index, or Stream On-Chain Data](/build/indexer) Query Indexer API, index contracts, stream raw transactions. * [Apply for a Grant](https://aptosnetwork.com/grants) Connect * [GitHub Developer Discussions](https://github.com/aptos-labs/aptos-developer-discussions/discussions) * [Ecosystem Directory](https://aptosnetwork.com/ecosystem/directory) * [Discord](https://discord.gg/aptosnetwork) * [Telegram](https://t.me/aptos) # Get Started Building on Aptos > Learn how to build on Aptos with smart contracts, indexer queries, SDKs, APIs, and comprehensive developer resources ## What would you like to learn? [](#what-would-you-like-to-learn) [Smart Contracts](/build/smart-contracts) Learn how to write smart contracts on Aptos with the Move programming language. [Query Data](/build/indexer) Use the Aptos Indexer to query for on-chain data efficiently. [Blockchain Infrastructure](/network/blockchain/blockchain-deep-dive) Learn the different components of the Aptos blockchain's infrastructure. ## What developer tools should I use? [](#what-developer-tools-should-i-use) [SDKs](/build/sdks) Use our TypeScript, Python, Rust, and other SDKs to submit transactions and read on-chain data. [Indexer](/build/indexer) Query for on-chain data like account balances, historical transactions, NFTs by account, and more. [CLI](/build/cli) Compile and profile Move smart contracts, run a local network, and more with the Aptos CLI. 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? [](#coming-from-another-ecosystem) Quickly ramp up on some of the differences and similarities between Aptos and other ecosystems. [Ethereum / EVM to Aptos Cheatsheet](/build/get-started/ethereum-cheatsheet) [Solana / SVM to Aptos Cheatsheet](/build/get-started/solana-cheatsheet) [VM Comparison](/network/blockchain/move#comparison-to-other-vms) ## Do you have any examples? [](#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 [](#end-to-end-guides) [Your First Transaction](/build/guides/first-transaction) This tutorial describes how to generate and submit transactions to the Aptos blockchain, and verify these submitted transactions. [Your First NFT](/build/guides/your-first-nft) This tutorial describes how to create and transfer non-fungible assets on the Aptos blockchain. [Your First Fungible Asset](/build/guides/first-fungible-asset) This tutorial introduces how you can compile, deploy, and mint your own fungible asset (FA), named FACoin. ### Smart Contract guides [](#smart-contract-guides) See the [Smart Contract](/build/smart-contracts) section for more info [Create a Smart Contract](/build/guides/build-e2e-dapp/1-create-smart-contract) This is the first chapter of the tutorial on building an end-to-end dapp on Aptos. [Aptos Move Examples](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples) 30+ examples on how to develop Move on Aptos [Move Tutorial](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/move-tutorial) Covers the basics of programming with Move ### Interactive guides [](#interactive-guides) [Aptos Learn](https://learn.aptoslabs.com/en/workshops) Basic and advanced guides [Move Spiders](https://movespiders.com) Learn about Move with a friendly spider mascot by Move Spiders [Aptos Shores](https://www.aptosshores.com) Learn about Move with Aptos Shores ## How do I setup a full node or validator? [](#how-do-i-setup-a-full-node-or-validator) [Setup a full node](/network/nodes/full-node) [Setup a validator](/network/nodes/validator-node) # Ethereum to Aptos Migration Guide > Comprehensive comparison and migration guide for Ethereum developers transitioning to Aptos blockchain development Aptos is built to allow you to quickly prototype and scale secure production applications. It combines a fast, cost-efficient, and stable blockchain layer with Move’s compile-time safety that catches exploits before deployment, comprehensive tooling for rapid development, and a strong ecosystem of exchanges and bridges for seamless integration. ### High Level Overview [](#high-level-overview)
FeatureEthereumAptos
Account Addresses160-bit256-bit
Storage MindsetContract-based storageAccount centric mindset for code and data
Caller IDmsg.sender&signer reference
Smart ContractsSolidity, EVMMove, MoveVM
BenefitsMature, wide adoptionScalability, low latency, predictable fees
Transaction FeesVariable, can be highLower and more predictable
Sponsored TransactionsRequires third-party services or EIP-7702 wallet support (2025+)Natively supported via fee payer field. Geomi Gas Stations provides production infrastructure
Account StructureBalance in a single field, uses nonceModules and resources, uses sequence number
Data StoragePatricia Merkle TreesGlobal storage with resources and modules
UpgradeabilityProxy patternsDirect module upgrades
Safety & SecurityVulnerable to attacks like reentrancyMitigates common vulnerabilities
Dispatch TypeDynamic dispatchStatic dispatch
Frontend SDKEthers.js libraryAptos Typescript SDK
NFT StandardsERC-721, ERC-1155Digital Asset
FT StandardERC-20, factory patternSee Fungible Asset, copy paste in your module: use aptos_framework::fungible_asset...
Example CodeERC-20 (new contract per deploy)Fungible Asset (single reusable module)
Legacy [`Coin`](/build/smart-contracts/aptos-coin) documentation still covers the original standard; most new deployments should prefer the Fungible Asset module referenced above. ### Comparing Token Standards in Detail [](#comparing-token-standards-in-detail)
SolidityMove (Aptos)
Token StructureEach token is its own contract.Every token is a typed FungibleAsset instantiation that reuses the same published module.
Token StandardMust conform to standards like ERC-20; implementations can vary per deploy.Uniform interface and implementation enforced by the shared module; new tokens simply register a new type rather than redeploying code.
Balance StorageBalances stored in contract using a mapping structure.Resource-Oriented Balance: balances live in an extensible object owned by the user’s account.
Transfer MechanismTokens can be transferred without receiver’s explicit permission.Transfers can skip receiver permission, but only when the FA explicitly enables primary-store auto creation (visible in the token’s creation code).
### Comparing EVM and Move VM in Detail [](#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 StorageData is stored in the smart contract’s storage space.Data is stored across smart contracts, user accounts, and objects.
ParallelizationParallel execution is limited due to shared storage space.More parallel execution enabled due to flexible split storage design.
VM and Language IntegrationSeparate 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 OperationsImplementation of network operations can be complex and less direct.Critical operations like validator set management natively implemented in Move, allowing for direct execution.
Function CallingDynamic dispatch allows for arbitrary smart contract calls.Static dispatch aligns with a focus on security and predictable behavior.
Type SafetyContract types provide a level of type safety.Module structs and generics in Move offer robust type safety.
Transaction SafetyUses nonces for transaction ordering and safety.Uses sequence numbers for transaction ordering and safety.
Authenticated StorageYes, with smart contract storage.Yes, leveraging Move’s resource model.
Object AccessibilityObjects are not globally accessible; bound to smart contract scope.Guaranteed global accessibility of objects.
## Migration Tips for Ethereum Developers [](#migration-tips-for-ethereum-developers) * [Storage](#tab-panel-129) * [Authentication](#tab-panel-130) * [Resources & Abilities](#tab-panel-131) * [Upgradability](#tab-panel-132) * [Deploying Modules](#tab-panel-133) Ethereum stores all data in contract storage using mappings. Aptos uses an account-centric model where each account stores their own resources. Instead of a contract maintaining a `mapping(address => T)`, each user stores their own `T` resource at their address. ``` module my_hackathon_account::prototype { use std::string; use std::signer; // Unlike Solidity's mapping(address => string), each account stores their own resource struct MessageHolder has key, store, drop { message: string::String, } entry fun set_message(account: &signer, message: string::String) acquires MessageHolder { let addr = signer::address_of(account); // Check if resource exists at this account (like checking mapping[addr]) if (exists(addr)) { move_from(addr); // Remove old resource }; // Store resource at the user's address (in their account, not in contract storage!) move_to(account, MessageHolder { message }); } #[view] public fun get_message(addr: address): string::String acquires MessageHolder { assert!(exists(addr), 0); // Read message stored at the user's address borrow_global(addr).message }} ``` By default, modules deploy to your account address. For production apps, consider deploying to [Objects](/build/smart-contracts/objects), which creates a unique address per deployment and enables transferable code ownership. See [Using Objects](/build/smart-contracts/object/using-objects) for implementation details. Learn more: [`global storage operators`](https://aptos-labs.github.io/move-book/global-storage.html), [`structs and resources`](https://aptos-labs.github.io/move-book/structs-and-enums.html) On Ethereum, `msg.sender` is set by the EVM, but many bugs come from using `tx.origin` for auth or trusting user-supplied addresses. Aptos’ `&signer` goes further: it’s an unforgeable capability created only by the VM for actual transaction signers, so any function that requires `&signer` can’t be called with a spoofed identity. In dapps, wallets plus the [Aptos TypeScript SDK](/build/sdks/ts-sdk) and [wallet adapter](/build/sdks/wallet-adapter/wallets) bridge this signer identity from frontend to on-chain. ``` module my_hackathon_account::prototype { use std::string; use std::signer; struct MessageHolder has key, store, drop { message: string::String, } // Only the account owner can provide their &signer (unforgeable authentication) entry fun set_message(account: &signer, message: string::String) acquires MessageHolder { // Extract address from authenticated signer (no spoofing possible!) let addr = signer::address_of(account); if (exists(addr)) { move_from(addr); }; // account is guaranteed to be authentic move_to(account, MessageHolder { message }); } #[view] public fun get_message(addr: address): string::String acquires MessageHolder { assert!(exists(addr), 0); // Read message stored at the user's address borrow_global(addr).message }} ``` Create and fund an account using the [Aptos CLI](/build/cli): ``` aptos init ``` Learn more: [`signer`](https://aptos-labs.github.io/move-book/primitive-types.html) type, [`functions`](https://aptos-labs.github.io/move-book/functions.html) Move has four abilities: `copy`, `drop`, `store`, and `key`, which control how values can be used. In this example, MessageHolder deliberately omits `copy` so messages stored as resources can’t be duplicated; you generally avoid `copy` on any type that represents on-chain state or assets. `key` + `store` allow it to live in global storage at an address, and `drop` lets you destroy the old resource safely when overwriting it. ``` module my_hackathon_account::prototype { use std::string; use std::signer; // Resources: structs with 'key' ability that live in global storage // key = can be stored at account addresses (makes it a "resource") // store = can be stored inside other structs // drop = can be destroyed/discarded implicitly struct MessageHolder has key, store, drop { message: string::String, } entry fun set_message(account: &signer, message: string::String) acquires MessageHolder { let addr = signer::address_of(account); // The 'drop' ability allows implicit destruction if (exists(addr)) { move_from(addr); // Old resource is destroyed (requires 'drop') }; move_to(account, MessageHolder { message }); } #[view] public fun get_message(addr: address): string::String acquires MessageHolder { assert!(exists(addr), 0); // Read message stored at the user's address borrow_global(addr).message }} ``` Learn more: [`abilities`](https://aptos-labs.github.io/move-book/generics-and-abilities.html), [`structs and resources`](https://aptos-labs.github.io/move-book/structs-and-enums.html) Aptos packages support two upgrade policies: `compatible` (default; only backward-compatible changes allowed) and `immutable` (no upgrades allowed). By default, packages published with the [Aptos CLI](/build/cli) using `aptos move publish` use the **compatible** policy, which lets you push new versions as long as you don’t break struct layouts or public function signatures. To prevent all future upgrades, set the immutable policy: ``` aptos move publish --upgrade-policy immutable ``` Or configure in your `Move.toml`: ``` [package]name = "MyPackage"version = "1.0.0"upgrade_policy = "immutable" ``` See [Package Upgrades](https://aptos-labs.github.io/move-book/cli-deploy.html) for the exact compatibility rules. On Ethereum you “deploy a contract to a new address.” On Aptos you **publish a package** of Move modules to an account (or object) address using the [Aptos CLI](/build/cli). Publish your package: ``` aptos move publish ``` Call an `entry` function after deployment: ``` aptos move run --function-id 'your_address::module_name::function_name' ``` Both account-based publishing and object-based deployment (via `aptos move deploy-object`) respect the package’s upgrade policy. See [Your First Move Module](/build/guides/first-move-module) for a complete walkthrough and [Objects](/build/smart-contracts/objects) for object-centric patterns. # Your First Transaction > Create and submit your first transaction on Aptos blockchain - transfer coins between accounts with TypeScript and Python examples. Transactions are the fundamental way to change data on the Aptos blockchain. Think of them like sending a package: you need to specify what you’re sending, who it’s going to, and then track it until delivery is confirmed. In blockchain terms, transactions allow you to transfer coins, call smart contract functions, and update on-chain state. This tutorial will guide you through creating and submitting your first transaction on the Aptos blockchain. You’ll learn how to: 1. Set up your development environment 2. Create test accounts and fund them 3. Build a transaction to transfer coins 4. Simulate the transaction to estimate costs 5. Sign and submit the transaction 6. Verify the transaction was executed successfully ## 1\. Setting Up Your Environment [](#1-setting-up-your-environment) * [TypeScript](#tab-panel-153) * [Python](#tab-panel-154) Before we can create transactions, we need to set up our development environment with the necessary tools and SDKs. 1. Install the TypeScript SDK Install the TypeScript SDK using your preferred package manager: * [npm](#tab-panel-134) * [yarn](#tab-panel-135) * [pnpm](#tab-panel-136) ``` npm install @aptos-labs/ts-sdk ``` ``` yarn add @aptos-labs/ts-sdk ``` ``` pnpm add @aptos-labs/ts-sdk ``` 2. Create a project directory Create a new directory for your project: ``` mkdir my-first-transactioncd my-first-transaction ``` 3. Create a new file Create a new file named `transaction.ts`: * [Mac/Linux](#tab-panel-137) * [Windows](#tab-panel-138) ``` touch transaction.ts ``` ``` type nul > transaction.ts ``` Before we can create transactions, we need to set up our development environment with the necessary tools and SDKs. 1. Install the Python SDK Install the Python SDK using pip: ``` pip install aptos-sdk ``` 2. Create a project directory Create a new directory for your project: ``` mkdir my-first-transactioncd my-first-transaction ``` 3. Create a new file Create a new file named `transaction.py`: * [Mac/Linux](#tab-panel-139) * [Windows](#tab-panel-140) ``` touch transaction.py ``` ``` type nul > transaction.py ``` ## 2\. Creating Test Accounts [](#2-creating-test-accounts) * [TypeScript](#tab-panel-143) * [Python](#tab-panel-144) In blockchain, all transactions must come from an account. Let’s create two test accounts: one to send coins (Alice) and one to receive them (Bob). 1. Set up the client First, we need to initialize the Aptos client that will connect to the blockchain. Open `transaction.ts` in your editor and add: ``` import { Account, Aptos, AptosConfig, Network,} from "@aptos-labs/ts-sdk"; async function main() { // Initialize the Aptos client const config = new AptosConfig({ network: Network.DEVNET }); const aptos = new Aptos(config); console.log("Connected to Aptos devnet"); // More code will go here} main().catch(console.error); ``` 2. Generate accounts Add this code inside your `main()` function to create two accounts - Alice (sender) and Bob (receiver): ``` // Generate two accountsconst alice = Account.generate();const bob = Account.generate(); console.log("=== Addresses ===");console.log(`Alice's address: ${alice.accountAddress}`);console.log(`Bob's address: ${bob.accountAddress}`); ``` 3. Fund the accounts Add this code after generating the accounts to get test coins from the faucet: ``` // Fund the accounts with test APT from the devnet faucetconsole.log("\n=== Funding accounts ===");await aptos.fundAccount({ accountAddress: alice.accountAddress, amount: 100_000_000, // 1 APT = 100,000,000 octas});console.log("Accounts funded successfully"); // Check initial balancesconst aliceBalance = await aptos.getAccountAPTAmount({ accountAddress: alice.accountAddress,});const bobBalance = await aptos.getAccountAPTAmount({ accountAddress: bob.accountAddress,}); console.log("\n=== Initial Balances ===");console.log(`Alice: ${aliceBalance} octas`);console.log(`Bob: ${bobBalance} octas`); ``` 4. Run the code Let’s test our code so far: ``` npx ts-node transaction.ts ``` You should see output similar to: ``` Connected to Aptos devnet=== Addresses ===Alice's address: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaBob's address: 0x7af2d6c93a2feafc9b69b5e8ad9d6b513b260f62f23f3a384a3a2e4a84694a9b === Funding accounts ===Accounts funded successfully === Initial Balances ===Alice: 100000000 octasBob: 0 octas ``` In blockchain, all transactions must come from an account. Let’s create two test accounts: one to send coins (Alice) and one to receive them (Bob). 1. Set up the client First, we need to initialize the Aptos client that will connect to the blockchain. Open `transaction.py` in your editor and add: ``` import asynciofrom aptos_sdk.account import Accountfrom aptos_sdk.async_client import FaucetClient, RestClientfrom aptos_sdk.transactions import EntryFunction, TransactionPayload, TransactionArgument, RawTransactionfrom aptos_sdk.bcs import Serializerimport time # Network configurationNODE_URL = "https://fullnode.devnet.aptoslabs.com/v1"FAUCET_URL = "https://faucet.devnet.aptoslabs.com" async def main(): # Initialize the clients rest_client = RestClient(NODE_URL) faucet_client = FaucetClient(FAUCET_URL, rest_client) print("Connected to Aptos devnet") # More code will go here if __name__ == "__main__": asyncio.run(main()) ``` 2. Generate accounts Add this code inside your `main()` function to create two accounts - Alice (sender) and Bob (receiver): ``` # Generate two accountsalice = Account.generate()bob = Account.generate() print("=== Addresses ===")print(f"Alice's address: {alice.address()}")print(f"Bob's address: {bob.address()}") ``` 3. Fund the accounts Add this code after generating the accounts to get test coins from the faucet: ``` # Fund the accounts with test APT from the devnet faucetprint("\n=== Funding accounts ===")alice_amount = 100_000_000 # 1 APT = 100,000,000 octasbob_amount = 0 # Bob starts with 0 APT await faucet_client.fund_account(alice.address(), alice_amount)print("Account funded successfully") # Check initial balancesalice_balance = await rest_client.account_balance(alice.address())bob_balance = await rest_client.account_balance(bob.address()) print("\n=== Initial Balances ===")print(f"Alice: {alice_balance} octas")print(f"Bob: {bob_balance} octas") ``` 4. Run the code Let’s test our code so far: ``` python transaction.py ``` You should see output similar to: ``` Connected to Aptos devnet=== Addresses ===Alice's address: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaBob's address: 0x7af2d6c93a2feafc9b69b5e8ad9d6b513b260f62f23f3a384a3a2e4a84694a9b === Funding accounts ===Accounts funded successfully === Initial Balances ===Alice: 100000000 octasBob: 0 octas ``` ## 3\. Building a Transaction [](#3-building-a-transaction) * [TypeScript](#tab-panel-145) * [Python](#tab-panel-146) Now that we have funded accounts, let’s create a transaction to transfer coins from Alice to Bob. This is like filling out a form specifying what you want to send and to whom. 1. Understand transaction structure A transaction in Aptos has several key components: 1. **Sender**: The account initiating the transaction (Alice) 2. **Function**: The on-chain function to call (in this case, a coin transfer) 3. **Arguments**: Data needed by the function (recipient address and amount) 4. **Gas parameters**: Maximum gas amount and gas unit price 5. **Expiration time**: When the transaction is no longer valid if not executed 6. **Sequence number**: A counter that prevents replay attacks 2. Build the transaction Let’s add code to build a transaction that transfers 1000 octas from Alice to Bob: Add this code to your `main()` function: ``` // 1. Build the transactionconsole.log("\n=== 1. Building the transaction ===");const transaction = await aptos.transaction.build.simple({ sender: alice.accountAddress, data: { function: "0x1::aptos_account::transfer", functionArguments: [bob.accountAddress, 1000], // Transfer 1000 octas },});console.log("Transaction built successfully"); // Access transaction details from the raw transactionconst rawTxn = transaction.rawTransaction;console.log(`Sender: ${rawTxn.sender}`);console.log(`Sequence Number: ${rawTxn.sequence_number}`);console.log(`Max Gas Amount: ${rawTxn.max_gas_amount}`);console.log(`Gas Unit Price: ${rawTxn.gas_unit_price}`);console.log(`Expiration Timestamp: ${new Date(Number(rawTxn.expiration_timestamp_secs) * 1000).toISOString()}`); ``` Now that we have funded accounts, let’s create a transaction to transfer coins from Alice to Bob. This is like filling out a form specifying what you want to send and to whom. 1. Understand transaction structure A transaction in Aptos has several key components: 1. **Sender**: The account initiating the transaction (Alice) 2. **Function**: The on-chain function to call (in this case, a coin transfer) 3. **Arguments**: Data needed by the function (recipient address and amount) 4. **Gas parameters**: Maximum gas amount and gas unit price 5. **Expiration time**: When the transaction is no longer valid if not executed 6. **Sequence number**: A counter that prevents replay attacks 2. Build the transaction Add the following code to your `main()` function to build a transaction that transfers 1000 octas from Alice to Bob: ``` # 1. Build the transactionprint("\n=== 1. Building the transaction ===") # Create the entry function payload# This specifies which function to call and with what argumentsentry_function = EntryFunction.natural( "0x1::aptos_account", # Module address and name "transfer", # Function name [], # Type arguments (empty for this function) [ # Function arguments with their serialization type TransactionArgument(bob.address(), Serializer.struct), # Recipient address TransactionArgument(1000, Serializer.u64), # Amount to transfer (1000 octas) ],) # Get the chain ID for the transactionchain_id = await rest_client.chain_id() # Get the sender's current sequence numberaccount_data = await rest_client.account(alice.address())sequence_number = int(account_data["sequence_number"]) # Create the raw transaction with all required fieldsraw_transaction = RawTransaction( sender=alice.address(), # Sender's address sequence_number=sequence_number, # Sequence number to prevent replay attacks payload=TransactionPayload(entry_function), # The function to call max_gas_amount=2000, # Maximum gas units to use gas_unit_price=100, # Price per gas unit in octas expiration_timestamps_secs=int(time.time()) + 600, # Expires in 10 minutes chain_id=chain_id, # Chain ID to ensure correct network) print("Transaction built successfully")print(f"Sender: {raw_transaction.sender}")print(f"Sequence Number: {raw_transaction.sequence_number}")print(f"Max Gas Amount: {raw_transaction.max_gas_amount}")print(f"Gas Unit Price: {raw_transaction.gas_unit_price}")print(f"Expiration Timestamp: {time.ctime(raw_transaction.expiration_timestamps_secs)}") ``` ## 4\. Simulating the Transaction [](#4-simulating-the-transaction) * [TypeScript](#tab-panel-147) * [Python](#tab-panel-148) Before submitting a transaction, it’s wise to simulate it first to estimate the gas cost. This is like checking shipping costs before sending a package. 1. Simulate the transaction Add this code after building the transaction: ``` // 2. Simulate the transactionconsole.log("\n=== 2. Simulating the transaction ===");const [simulationResult] = await aptos.transaction.simulate.simple({ signerPublicKey: alice.publicKey, transaction,}); const gasUsed = parseInt(simulationResult.gas_used);const gasUnitPrice = parseInt(simulationResult.gas_unit_price);console.log(`Estimated gas units: ${gasUsed}`);console.log(`Estimated gas cost: ${gasUsed * gasUnitPrice} octas`);console.log(`Transaction would ${simulationResult.success ? "succeed" : "fail"}`); ``` Before submitting a transaction, it’s wise to simulate it first to estimate the gas cost. This is like checking shipping costs before sending a package. 1. Simulate the transaction Add this code after building the transaction: ``` # 2. Simulate the transactionprint("\n=== 2. Simulating the transaction ===") # Create a BCS transaction for simulation# This doesn't actually submit the transaction to the blockchainsimulation_transaction = await rest_client.create_bcs_transaction(alice, TransactionPayload(entry_function)) # Simulate the transaction to estimate gas costs and check for errorssimulation_result = await rest_client.simulate_transaction(simulation_transaction, alice) # Extract and display the simulation resultsgas_used = int(simulation_result[0]['gas_used'])gas_unit_price = int(simulation_result[0]['gas_unit_price'])success = simulation_result[0]['success'] print(f"Estimated gas units: {gas_used}")print(f"Estimated gas cost: {gas_used * gas_unit_price} octas")print(f"Transaction would {'succeed' if success else 'fail'}") ``` ## 5\. Signing and Submitting the Transaction [](#5-signing-and-submitting-the-transaction) * [TypeScript](#tab-panel-149) * [Python](#tab-panel-150) Now that we’ve built and simulated the transaction, we need to sign it with Alice’s private key and submit it to the blockchain. 1. Sign the transaction Signing proves that Alice authorized this transaction: Add this code after simulating the transaction: ``` // 3. Sign the transactionconsole.log("\n=== 3. Signing the transaction ===");const senderAuthenticator = aptos.transaction.sign({ signer: alice, transaction,});console.log("Transaction signed successfully"); ``` 2. Submit the transaction Add this code after signing the transaction to submit the signed transaction to the blockchain: ``` // 4. Submit the transactionconsole.log("\n=== 4. Submitting the transaction ===");const pendingTransaction = await aptos.transaction.submit.simple({ transaction, senderAuthenticator,});console.log(`Transaction submitted with hash: ${pendingTransaction.hash}`); ``` Now that we’ve built and simulated the transaction, we need to sign it with Alice’s private key and submit it to the blockchain. 1. Sign the transaction Signing proves that Alice authorized this transaction: Add this code after simulating the transaction: ``` # 3. Sign the transactionprint("\n=== 3. Signing the transaction ===") # Sign the raw transaction with the sender's private key# This creates a cryptographic signature that proves the sender authorized this transactionsigned_transaction = await rest_client.create_bcs_signed_transaction( alice, # Account with the private key TransactionPayload(entry_function), # The payload from our transaction sequence_number=sequence_number # Use the same sequence number as before) print("Transaction signed successfully")# We can't easily extract the signature from the signed transaction object,# but we can confirm it was created ``` 2. Submit the transaction Add this code after signing the transaction to submit the signed transaction to the blockchain: ``` # 4. Submit the transactionprint("\n=== 4. Submitting the transaction ===") # Submit the signed transaction to the blockchain# This broadcasts the transaction to the network for processingtx_hash = await rest_client.submit_bcs_transaction(signed_transaction) print(f"Transaction submitted with hash: {tx_hash}") ``` ## 6\. Waiting for Confirmation [](#6-waiting-for-confirmation) * [TypeScript](#tab-panel-151) * [Python](#tab-panel-152) After submitting a transaction, we need to wait for it to be processed by the blockchain. This is like waiting for a package to be delivered. 1. Wait for transaction completion Add this code after submitting the transaction: ``` // 5. Wait for the transaction to completeconsole.log("\n=== 5. Waiting for transaction completion ===");const txnResult = await aptos.waitForTransaction({ transactionHash: pendingTransaction.hash,});console.log(`Transaction completed with status: ${txnResult.success ? "SUCCESS" : "FAILURE"}`); // If you want to see more details about the transaction:console.log(`VM Status: ${txnResult.vm_status}`);console.log(`Gas used: ${txnResult.gas_used}`); ``` 2. Verify the results Add this code after waiting for the transaction to check the balances and confirm the transfer worked: ``` // Check final balancesconst aliceFinalBalance = await aptos.getAccountAPTAmount({ accountAddress: alice.accountAddress,});const bobFinalBalance = await aptos.getAccountAPTAmount({ accountAddress: bob.accountAddress,}); console.log("\n=== Final Balances ===");console.log(`Alice: ${aliceFinalBalance} octas (spent ${aliceBalance - aliceFinalBalance} octas on transfer and gas)`);console.log(`Bob: ${bobFinalBalance} octas (received 1000 octas)`); ``` 3. Run the complete code ``` npx ts-node transaction.ts ``` You should see output similar to: ``` Connected to Aptos devnet=== Addresses ===Alice's address: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaBob's address: 0x7af2d6c93a2feafc9b69b5e8ad9d6b513b260f62f23f3a384a3a2e4a84694a9b === Funding accounts ===Accounts funded successfully === Initial Balances ===Alice: 100000000 octasBob: 0 octas === 1. Building the transaction ===Transaction built successfullySender: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaSequence Number: 0Max Gas Amount: 20000Gas Unit Price: 100Expiration Timestamp: 2025-03-05T22:59:21.000Z === 2. Simulating the transaction ===Estimated gas units: 146Estimated gas cost: 14600 octasTransaction would succeed === 3. Signing the transaction ===Transaction signed successfully === 4. Submitting the transaction ===Transaction submitted with hash: 0x3a8a3e34a1c64ad9d7636a3a827b7ec3bb12d73825b36fa06d425c5a3b42cccc === 5. Waiting for transaction completion ===Transaction completed with status: SUCCESSVM Status: Executed successfullyGas used: 146 === Final Balances ===Alice: 99984400 octas (spent 15600 octas on transfer and gas)Bob: 1000 octas (received 1000 octas) ``` After submitting a transaction, we need to wait for it to be processed by the blockchain. This is like waiting for a package to be delivered. 1. Wait for transaction completion Add this code after submitting the transaction: ``` # 5. Wait for the transaction to completeprint("\n=== 5. Waiting for transaction completion ===") # Wait for the transaction to be processed by the blockchain# This polls the blockchain until the transaction is confirmedawait rest_client.wait_for_transaction(tx_hash) # Get the transaction details to check its statustransaction_details = await rest_client.transaction_by_hash(tx_hash)success = transaction_details["success"]vm_status = transaction_details["vm_status"]gas_used = transaction_details["gas_used"] print(f"Transaction completed with status: {'SUCCESS' if success else 'FAILURE'}")print(f"VM Status: {vm_status}")print(f"Gas used: {gas_used}") ``` 2. Verify the results Add this code after waiting for the transaction to check the balances and confirm the transfer worked: ``` # Check final balancesalice_final_balance = await rest_client.account_balance(alice.address())bob_final_balance = await rest_client.account_balance(bob.address()) print("\n=== Final Balances ===")print(f"Alice: {alice_final_balance} octas (spent {alice_balance - alice_final_balance} octas on transfer and gas)")print(f"Bob: {bob_final_balance} octas (received 1000 octas)") ``` 3. Run the complete code ``` python transaction.py ``` You should see output similar to: ``` Connected to Aptos devnet=== Addresses ===Alice's address: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaBob's address: 0x7af2d6c93a2feafc9b69b5e8ad9d6b513b260f62f23f3a384a3a2e4a84694a9b === Funding accounts ===Accounts funded successfully === Initial Balances ===Alice: 100000000 octasBob: 0 octas === 1. Building the transaction ===Transaction built successfullySender: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aaSequence Number: 0Max Gas Amount: 2000Gas Unit Price: 100Expiration Timestamp: Wed Mar 05 22:59:21 2025 === 2. Simulating the transaction ===Estimated gas units: 146Estimated gas cost: 14600 octasTransaction would succeed === 3. Signing the transaction ===Transaction signed successfully === 4. Submitting the transaction ====== 3. Signing the transaction ===Transaction signed successfully === 4. Submitting the transaction ===Transaction submitted with hash: 0x3a8a3e34a1c64ad9d7636a3a827b7ec3bb12d73825b36fa06d425c5a3b42cccc === 5. Waiting for transaction completion ===Transaction completed with status: SUCCESSVM Status: Executed successfullyGas used: 146 === Final Balances ===Alice: 99984400 octas (spent 15600 octas on transfer and gas)Bob: 1000 octas (received 1000 octas) ``` ## 7\. (Optional) Explore Your Transaction On-Chain [](#7-optional-explore-your-transaction-on-chain) Now that you’ve successfully executed a transaction, you can explore it on the Aptos Explorer. This will help you understand how transactions are recorded on the blockchain and what information is publicly available. 1. Copy your transaction hash From your terminal output, copy the transaction hash that was printed after submission. It looks something like this: ``` Transaction submitted with hash: 0x3a8a3e34a1c64ad9d7636a3a827b7ec3bb12d73825b36fa06d425c5a3b42cccc ``` 2. Open the Aptos Explorer Go to the [Aptos Explorer](https://explorer.aptoslabs.com/?network=devnet). 3. Ensure you are on Devnet network Look for “Devnet” in the top right corner, or switch networks by clicking the dropdown and selecting Devnet. ![Switching to Devnet network in Aptos Explorer](/_vercel/image?url=_astro%2Fexplorer_devnet.D3PWblc6.png&w=320&q=100&dpl=dpl_DNuD117vkaPEPQAH7HWLuvPnauoG) 4. Search for your transaction Paste your transaction hash into the search bar in the middle of the page. Caution Do not press enter! There is a known bug where searching with Enter does not work. 5. View the transaction details Wait for the results to appear, then click on the transaction hash to view its details. You should see information about your transaction, including: * Status (should be “Success”) * Timestamp * Gas used * Sender and recipient addresses * Amount transferred 6. Explore further From the transaction details page, you can: * Click on the sender or recipient addresses to view their account details * See the exact changes made to the blockchain state * View the transaction payload and arguments ## 8\. Next Steps [](#8-next-steps) Congratulations! You’ve successfully created and executed your first transaction on the Aptos blockchain. Here are some suggestions for what to explore next: **Learn about more complex transactions**: * [Multi-Agent Signatures](/build/sdks/ts-sdk/building-transactions/multi-agent-transactions) - Transactions requiring multiple signers * [Sponsoring Transactions](/build/sdks/ts-sdk/building-transactions/sponsoring-transactions) - Having another account pay gas fees * [Batching Transactions](/build/sdks/ts-sdk/building-transactions/batching-transactions) - Sending multiple transactions efficiently **Explore smart contracts or account basics**: * [Your First Move Module](/build/guides/first-move-module) - Create your own smart contract * [Account Basics](/network/blockchain/accounts) [Join the Aptos Discord](https://discord.gg/aptoslabs) and share what you’re building! ## Full Code Sample [](#full-code-sample) The complete code samples below combine all the snippets we’ve covered in this tutorial: * [TypeScript](#tab-panel-141) * [Python](#tab-panel-142) ``` import { Account, Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk"; async function main() { // Initialize the Aptos client const config = new AptosConfig({ network: Network.DEVNET }); const aptos = new Aptos(config); console.log("Connected to Aptos devnet"); // More code will go here // Generate two accounts const alice = Account.generate(); const bob = Account.generate(); console.log("=== Addresses ==="); console.log(`Alice's address: ${alice.accountAddress}`); console.log(`Bob's address: ${bob.accountAddress}`); // Fund the accounts with test APT from the devnet faucet console.log("\n=== Funding accounts ==="); await aptos.fundAccount({ accountAddress: alice.accountAddress, amount: 100_000_000, // 1 APT = 100,000,000 octas }); await aptos.fundAccount({ accountAddress: bob.accountAddress, amount: 0, // Bob starts with 0 APT }); console.log("Accounts funded successfully"); // Check initial balances const aliceBalance = await aptos.getAccountAPTAmount({ accountAddress: alice.accountAddress, }); const bobBalance = await aptos.getAccountAPTAmount({ accountAddress: bob.accountAddress, }); console.log("\n=== Initial Balances ==="); console.log(`Alice: ${aliceBalance} octas`); console.log(`Bob: ${bobBalance} octas`); // 1. Build the transaction console.log("\n=== 1. Building the transaction ==="); const transaction = await aptos.transaction.build.simple({ sender: alice.accountAddress, data: { function: "0x1::aptos_account::transfer", functionArguments: [bob.accountAddress, 1000], // Transfer 1000 octas }, }); console.log("Transaction built successfully"); // Use type assertion to bypass TypeScript's type checking const txnAny = transaction as any; console.log(`Sender: ${alice.accountAddress}`); // Use the known sender address console.log(`Sequence Number: ${txnAny.sequenceNumber || "N/A"}`); console.log(`Max Gas Amount: ${txnAny.maxGasAmount || "N/A"}`); console.log(`Gas Unit Price: ${txnAny.gasUnitPrice || "N/A"}`); console.log( `Expiration Timestamp: ${new Date( Number(txnAny.expirationTimestampSecs || 0) * 1000 ).toISOString()}` ); // 2. Simulate the transaction console.log("\n=== 2. Simulating the transaction ==="); const [simulationResult] = await aptos.transaction.simulate.simple({ signerPublicKey: alice.publicKey, transaction, }); console.log(`Estimated gas units: ${simulationResult.gas_used}`); console.log( `Estimated gas cost: ${ Number(simulationResult.gas_used) * Number(simulationResult.gas_unit_price) } octas` ); console.log( `Transaction would ${simulationResult.success ? "succeed" : "fail"}` ); // 3. Sign the transaction console.log("\n=== 3. Signing the transaction ==="); const senderAuthenticator = aptos.transaction.sign({ signer: alice, transaction, }); console.log("Transaction signed successfully"); // Use type assertion to bypass TypeScript's type checking const authAny = senderAuthenticator as any; const signatureStr = typeof authAny.signature === 'string' ? authAny.signature : JSON.stringify(authAny.signature || ''); console.log(`Signature: ${signatureStr.slice(0, 20)}...`); // 4. Submit the transaction console.log("\n=== 4. Submitting the transaction ==="); const pendingTransaction = await aptos.transaction.submit.simple({ transaction, senderAuthenticator, }); console.log(`Transaction submitted with hash: ${pendingTransaction.hash}`); // 5. Wait for the transaction to complete console.log("\n=== 5. Waiting for transaction completion ==="); const txnResult = await aptos.waitForTransaction({ transactionHash: pendingTransaction.hash, }); console.log( `Transaction completed with status: ${ txnResult.success ? "SUCCESS" : "FAILURE" }` ); // If you want to see more details about the transaction: console.log(`VM Status: ${txnResult.vm_status}`); console.log(`Gas used: ${txnResult.gas_used}`); // Check final balances const aliceFinalBalance = await aptos.getAccountAPTAmount({ accountAddress: alice.accountAddress, }); const bobFinalBalance = await aptos.getAccountAPTAmount({ accountAddress: bob.accountAddress, }); console.log("\n=== Final Balances ==="); console.log( `Alice: ${aliceFinalBalance} octas (spent ${ aliceBalance - aliceFinalBalance } octas on transfer and gas)` ); console.log(`Bob: ${bobFinalBalance} octas (received 1000 octas)`);} main().catch(console.error); ``` ``` import asynciofrom aptos_sdk.account import Accountfrom aptos_sdk.async_client import FaucetClient, RestClientfrom aptos_sdk.transactions import EntryFunction, TransactionPayload, TransactionArgument, RawTransactionfrom aptos_sdk.bcs import Serializerimport time # Network configurationNODE_URL = "https://fullnode.devnet.aptoslabs.com/v1"FAUCET_URL = "https://faucet.devnet.aptoslabs.com" async def main(): # Initialize the clients rest_client = RestClient(NODE_URL) faucet_client = FaucetClient(FAUCET_URL, rest_client) print("Connected to Aptos devnet") # Generate two accounts alice = Account.generate() bob = Account.generate() print("=== Addresses ===") print(f"Alice's address: {alice.address()}") print(f"Bob's address: {bob.address()}") # More code will go here # Fund the accounts with test APT from the devnet faucet print("\n=== Funding accounts ===") alice_amount = 100_000_000 # 1 APT = 100,000,000 octas bob_amount = 0 # Bob starts with 0 APT await faucet_client.fund_account(alice.address(), alice_amount) await faucet_client.fund_account(bob.address(), bob_amount) print("Accounts funded successfully") # Check initial balances alice_balance = await rest_client.account_balance(alice.address()) bob_balance = await rest_client.account_balance(bob.address()) print("\n=== Initial Balances ===") print(f"Alice: {alice_balance} octas") print(f"Bob: {bob_balance} octas") # 1. Build the transaction print("\n=== 1. Building the transaction ===") # Create the entry function payload # This specifies which function to call and with what arguments entry_function = EntryFunction.natural( "0x1::aptos_account", # Module address and name "transfer", # Function name [], # Type arguments (empty for this function) [ # Function arguments with their serialization type TransactionArgument(bob.address(), Serializer.struct), # Recipient address TransactionArgument(1000, Serializer.u64), # Amount to transfer (1000 octas) ], ) # Get the chain ID for the transaction chain_id = await rest_client.chain_id() # Get the sender's current sequence number account_data = await rest_client.account(alice.address()) sequence_number = int(account_data["sequence_number"]) # Create the raw transaction with all required fields raw_transaction = RawTransaction( sender=alice.address(), # Sender's address sequence_number=sequence_number, # Sequence number to prevent replay attacks payload=TransactionPayload(entry_function), # The function to call max_gas_amount=2000, # Maximum gas units to use gas_unit_price=100, # Price per gas unit in octas expiration_timestamps_secs=int(time.time()) + 600, # Expires in 10 minutes chain_id=chain_id, # Chain ID to ensure correct network ) print("Transaction built successfully") print(f"Sender: {raw_transaction.sender}") print(f"Sequence Number: {raw_transaction.sequence_number}") print(f"Max Gas Amount: {raw_transaction.max_gas_amount}") print(f"Gas Unit Price: {raw_transaction.gas_unit_price}") print(f"Expiration Timestamp: {time.ctime(raw_transaction.expiration_timestamps_secs)}") # 2. Simulate the transaction print("\n=== 2. Simulating the transaction ===") # Create a BCS transaction for simulation # This doesn't actually submit the transaction to the blockchain simulation_transaction = await rest_client.create_bcs_transaction(alice, TransactionPayload(entry_function)) # Simulate the transaction to estimate gas costs and check for errors simulation_result = await rest_client.simulate_transaction(simulation_transaction, alice) # Extract and display the simulation results gas_used = int(simulation_result[0]['gas_used']) gas_unit_price = int(simulation_result[0]['gas_unit_price']) success = simulation_result[0]['success'] print(f"Estimated gas units: {gas_used}") print(f"Estimated gas cost: {gas_used * gas_unit_price} octas") print(f"Transaction would {'succeed' if success else 'fail'}") # 3. Sign the transaction print("\n=== 3. Signing the transaction ===") # Sign the raw transaction with the sender's private key # This creates a cryptographic signature that proves the sender authorized this transaction signed_transaction = await rest_client.create_bcs_signed_transaction( alice, # Account with the private key TransactionPayload(entry_function), # The payload from our transaction sequence_number=sequence_number # Use the same sequence number as before ) print("Transaction signed successfully") # We can't easily extract the signature from the signed transaction object, # but we can confirm it was created # 4. Submit the transaction print("\n=== 4. Submitting the transaction ===") # Submit the signed transaction to the blockchain # This broadcasts the transaction to the network for processing tx_hash = await rest_client.submit_bcs_transaction(signed_transaction) print(f"Transaction submitted with hash: {tx_hash}") # 5. Wait for the transaction to complete print("\n=== 5. Waiting for transaction completion ===") # Wait for the transaction to be processed by the blockchain # This polls the blockchain until the transaction is confirmed await rest_client.wait_for_transaction(tx_hash) # Get the transaction details to check its status transaction_details = await rest_client.transaction_by_hash(tx_hash) success = transaction_details["success"] vm_status = transaction_details["vm_status"] gas_used = transaction_details["gas_used"] print(f"Transaction completed with status: {'SUCCESS' if success else 'FAILURE'}") print(f"VM Status: {vm_status}") print(f"Gas used: {gas_used}") # Check final balances alice_final_balance = await rest_client.account_balance(alice.address()) bob_final_balance = await rest_client.account_balance(bob.address()) print("\n=== Final Balances ===") print(f"Alice: {alice_final_balance} octas (spent {alice_balance - alice_final_balance} octas on transfer and gas)") print(f"Bob: {bob_final_balance} octas (received 1000 octas)")if __name__ == "__main__": asyncio.run(main()) ``` # Your First Move Module > Learn to compile, test, publish, and interact with Move smart contracts on Aptos blockchain from setup to deployment. The Aptos blockchain allows developers to write Turing complete smart contracts (called “modules”) with the secure-by-design Move language. Smart contracts enable users to send money with the blockchain, but also write arbitrary code, even games! It all starts with the Aptos CLI creating an account which will store the deployed (”published”) Move module. This tutorial will help you understand Move Modules by guiding you through setting up a minimal Aptos environment, then how to compile, test, publish and interact with Move modules on the Aptos Blockchain. You will learn how to: 1. Setup your environment, install the CLI 2. Create a devnet account and fund it 3. Compile and test a Move module 4. Publish (or “deploy”) a Move module to the Aptos blockchain 5. Interact with the module 6. Keep building with Aptos (next steps) ## 1\. Setup [](#1-setup) Changes to the blockchain are called “transactions”, and they require an account to pay the network fee (”gas fee”). We will need to create an account with some APT to pay that fee and own the published contract. In order to do that, we will need to use the Aptos CLI. 1. Install the Aptos CLI [Install the Aptos CLI](/build/cli) (if you haven’t already). 2. Open a new terminal Open a new terminal window or tab. 3. Verify the installation Run `aptos --version` to verify you have it installed. ``` aptos --version ``` You should see a response like `aptos 4.6.1`. 4. Create a project folder Create a new folder for this tutorial by running: ``` mkdir my-first-module ``` 5. Navigate to the project folder Run `cd my-first-module` to go into your new folder. 6. Initialize your account Run `aptos init` and press ‘enter’ for each step of setup to create a test account on `devnet`. You should see a success message like this: ``` ---Aptos CLI is now set up for account 0x9ec1cfa30b885a5c9d595f32f3381ec16d208734913b587be9e210f60be9f9ba as profile default!{ "Result": "Success"} ``` ## 2\. (Optional) Explore What You Just Did On-Chain [](#2-optional-explore-what-you-just-did-on-chain) 1. Copy your account address Copy the address from the command line for your new account. The address looks like this `0x9ec1cfa30b885a5c9d595f32f3381ec16d208734913b587be9e210f60be9f9ba` and you can find it in the line: ``` Aptos CLI is now set up for account 0x9ec1cfa30b885a5c9d595f32f3381ec16d208734913b587be9e210f60be9f9ba as profile default! ``` 2. Open the Aptos Explorer Go to the [Aptos Explorer](https://explorer.aptoslabs.com/?network=devnet). This is the primary way to quickly check what is happening on devnet, testnet, or mainnet. We will use it later on to view our deployed contracts. 3. Ensure you are on Devnet network. Look for “Devnet” in the top right corner, or switch networks by clicking the “Mainnet” dropdown and selecting Devnet ![Switching to Devnet network in Aptos Explorer](/_vercel/image?url=_astro%2Fexplorer_devnet.D3PWblc6.png&w=320&q=100&dpl=dpl_DNuD117vkaPEPQAH7HWLuvPnauoG) 4. Search for your account Paste your newly created address into the search bar. Caution Do not press enter! There is a known bug where searching with Enter does not work. 5. View the search results Wait for the results to appear, then click the top result. 6. Check the transaction You should see your newly created account and a transaction with the faucet function, funding it with devnet tokens. ![Viewing Account in Aptos Explorer](/_vercel/image?url=_astro%2Fexplorer_account.DlK3EDU1.png&w=1280&q=100&dpl=dpl_DNuD117vkaPEPQAH7HWLuvPnauoG) 7. Verify your balance Click the “Coins” tab to see that you have 1 APT of the Aptos Coin. This will allow you to publish and interact with smart contracts on the aptos devnet. ## 3\. Writing and Compiling Your First Module [](#3-writing-and-compiling-your-first-module) Now that we have our environment set up and an account created, let’s write and compile our first Move module. Unlike Ethereum where contracts exist independently, Move ties everything to accounts - both modules and their resources. Let’s start with a simple example to understand the core concepts. ![Move Blockchain Diagram](/_vercel/image?url=_astro%2Fmove_blockchain.US8AdnUd.png&w=640&q=100&dpl=dpl_DNuD117vkaPEPQAH7HWLuvPnauoG) This diagram illustrates the relationship between module ownership, token ownership, and the Move blockchain state. It helps visualize how modules and resources are tied to accounts, emphasizing the unique aspects of Move’s design compared to other blockchain platforms. ### What is a Move Module? [](#what-is-a-move-module) Move modules are similar to smart contracts in other blockchains, with some key differences: * **Resources:** Unlike Solidity where state is stored in contract variables, Move uses “resources” - special data types that can only exist in one place at a time and are always tied to an account * **Module-based**: Rather than deploying entire contracts as independent units like in Solidity, Move code is organized into reusable modules that can share and handle resources across boundaries. Modules are more like standard library packages that can be published together or separately, offering finer-grained control over code organization. * **Safety by design:** Move’s type system and resource semantics help prevent common smart contract vulnerabilities ### Your First Move Module [](#your-first-move-module) Before we start, go to your VSCode (or Cursor) and install the [Move On Aptos](/build/smart-contracts/move-vscode-extension) VSCode extension. 1. Open VSCode (or Cursor) and navigate to the Extensions tab. 2. Search for `Move On Aptos` published by `aptoslabs` and install the extension. This extension will help us with the syntax highlighting, auto-completion, and other features that will make our development experience easier. Our first module will be a simple message storage system that allows accounts to store and retrieve messages. Let’s create a new move project within our `my-first-module` folder: 1. Initialize the project Initialize a new move project with `aptos move init --name my_first_module` This creates a project structure with a `sources` directory and a `Move.toml` file. 2. Create the module file Create a new file `sources/message.move` with our module code: ``` module my_first_module::message { use std::string; use std::signer; struct MessageHolder has key, store, drop { message: string::String, } public entry fun set_message(account: &signer, message: string::String) acquires MessageHolder { let account_addr = signer::address_of(account); if (exists(account_addr)) { move_from(account_addr); }; move_to(account, MessageHolder { message }); } public fun get_message(account_addr: address): string::String acquires MessageHolder { assert!(exists(account_addr), 0); let message_holder = borrow_global(account_addr); message_holder.message }} ``` Let’s break down this module: * We define a `MessageHolder` resource type that can store a string message * `set_message` allows an account to store a message * `get_message` allows anyone to retrieve a stored message * The `acquires` keyword indicates which resources the functions need access to (MessageHolder, in this case) * `move_to` and `move_from` handle the storage of resources under accounts 3. Compile the module Compile the Move module we just created with `aptos move compile --named-addresses my_first_module=default` You should see a message like this if it succeeded: ``` ❯ aptos move compile --named-addresses my_first_module=defaultCompiling, may take a little while to download git dependencies...UPDATING GIT DEPENDENCY https://github.com/aptos-labs/aptos-framework.gitINCLUDING DEPENDENCY AptosFrameworkINCLUDING DEPENDENCY AptosStdlibINCLUDING DEPENDENCY MoveStdlibBUILDING my_first_module{ "Result": [ "9ec1cfa30b885a5c9d595f32f3381ec16d208734913b587be9e210f60be9f9ba::message" ]} ``` Great job! We are now ready to test and debug. ## 4\. Testing and Debugging [](#4-testing-and-debugging) Testing and debugging are crucial parts of Move module development. Move has built-in support for unit testing and debug printing. 1. Add debug prints First, let’s modify our message module to add some debug prints. Update your `sources/message.move`: ``` module my_first_module::message { use std::string; use std::signer; use std::debug; // Add this for debug prints struct MessageHolder has key, store, drop { message: string::String, } public entry fun set_message(account: &signer, message: string::String) acquires MessageHolder { let account_addr = signer::address_of(account); debug::print(&message); // Print the message being set if (exists(account_addr)) { debug::print(&string::utf8(b"Updating existing message")); // Print debug info move_from(account_addr); } else { debug::print(&string::utf8(b"Creating new message")); // Print when creating new }; move_to(account, MessageHolder { message }); } public fun get_message(account_addr: address): string::String acquires MessageHolder { assert!(exists(account_addr), 0); let message_holder = borrow_global(account_addr); debug::print(&message_holder.message); // Print the retrieved message message_holder.message }} ``` 2. Create test file Create our tests: a new file `sources/message_tests.move` with: ``` #[test_only] module my_first_module::message_tests { use std::string; use std::signer; use my_first_module::message; #[test(sender= @my_first_module)] fun test_set_and_get_message(sender: &signer) { // Test setting a message message::set_message(sender, string::utf8(b"Hello World")); // Verify the message was set correctly let stored_message = message::get_message(signer::address_of(sender)); assert!(stored_message == string::utf8(b"Hello World"), 0) } #[test(sender=@my_first_module)] fun test_update_message(sender: &signer) { // Test setting a message message::set_message(sender, string::utf8(b"Hello World")); // Test updating the message message::set_message(sender, string::utf8(b"Hello Aptos")); // Verify the message was updated correctly let stored_message = message::get_message(signer::address_of(sender)); assert!(stored_message == string::utf8(b"Hello Aptos"), 0) } } ``` 3. Run the tests Now run the tests with `aptos move test --named-addresses my_first_module=default` You should see output if the tests pass: (See below for how to handle errors) ``` INCLUDING DEPENDENCY AptosFramework INCLUDING DEPENDENCY AptosStdlib INCLUDING DEPENDENCY MoveStdlib BUILDING my_first_module Running Move unit tests [debug] "Hello World" [debug] "Creating new message" [debug] "Hello World" [ PASS ] 0x852a264419a80b27771f072b5cae8c8b358d4450e135e134e065247376a4357a::message_tests::test_set_and_get_message [debug] "Hello World" [debug] "Creating new message" [debug] "Hello Aptos" [debug] "Updating existing message" [debug] "Hello Aptos" [ PASS ] 0x852a264419a80b27771f072b5cae8c8b358d4450e135e134e065247376a4357a::message_tests::test_update_message Test result: OK. Total tests: 2; passed: 2; failed: 0 { "Result": "Success" } ``` **If you encounter errors while testing, here are some common issues and solutions:** * Make sure all module dependencies are properly imported * Check that your account address matches in the `-named-addresses` parameter * Verify that test functions have the `#[test]` attribute * Ensure string literals are properly encoded ## 5\. Publishing Your Module [](#5-publishing-your-module) After successfully compiling and testing your module, you can publish it to the Aptos blockchain. This process deploys your code so that it’s accessible on-chain. 1. Publish the module Publish your module with `aptos move publish --named-addresses my_first_module=default` You’ll see output showing the compilation process and then a prompt asking about gas fees: ``` Compiling, may take a little while to download git dependencies...UPDATING GIT DEPENDENCY https://github.com/aptos-labs/aptos-framework.gitINCLUDING DEPENDENCY AptosFrameworkINCLUDING DEPENDENCY AptosStdlibINCLUDING DEPENDENCY MoveStdlibBUILDING my_first_modulepackage size 1271 bytesDo you want to submit a transaction for a range of [141300 - 211900] Octas at a gas unit price of 100 Octas? [yes/no] > ``` 2. Confirm the transaction Type `y` and press Enter to confirm the transaction. After confirmation, you’ll receive a response showing the transaction details: ``` { "Result": { "transaction_hash": "0x95fce7344b066abda10c07dbf1ffa83e0d9c7bd400e2b143682a6c8a5f179dc2", "gas_used": 1413, "gas_unit_price": 100, "sender": "9ec1cfa30b885a5c9d595f32f3381ec16d208734913b587be9e210f60be9f9ba", "sequence_number": 0, "success": true, "timestamp_us": 1735351260227638, "version": 273029731, "vm_status": "Executed successfully" }} ``` ### (Optional) Seeing Your Contract On-Chain [](#optional-seeing-your-contract-on-chain) After successful publication, you can verify your module is on-chain by following these steps: 1. Open the Explorer Go to the [Aptos Explorer](https://explorer.aptoslabs.com/?network=devnet) 2. Check the transaction Search for your account address. You should notice that there is a new transaction in your account, the `code::publish_package_txn` function. 3. View your balance Click the “Coins” tab to see that you now have less than 1 APT of the Aptos Coin. ![Explorer Coins View](/_vercel/image?url=_astro%2Fexplorer_coins.BHJq95xO.png&w=1280&q=100&dpl=dpl_DNuD117vkaPEPQAH7HWLuvPnauoG) You have spent a small amount on gas to deploy the contract so should have around `0.99855 APT` remaining. 4. Find your module Look under the “Modules” tab ![Exporer Modules View](/_vercel/image?url=_astro%2Fexplorer_modules.BhR9Jwde.png&w=1280&q=100&dpl=dpl_DNuD117vkaPEPQAH7HWLuvPnauoG) 5. Verify the module You should see your “message” module listed ## 6\. Interacting with Your Module [](#6-interacting-with-your-module) Now that your module is published, you can interact with it through the Aptos CLI: 1. Set a message Set a message using the CLI: ``` aptos move run --function-id 'default::message::set_message' --args 'string:Hello, Aptos!' ``` You’ll see a gas fee prompt similar to what you saw during publishing. 2. Confirm the transaction After confirming with `y`, you should get a success response like: ``` Transaction submitted: https://explorer.aptoslabs.com/txn/0x0c0b1e56a31d037280278327eb8fdfcc469a20213e5e65accf6e7c56af574449?network=devnet{ "Result": { "transaction_hash": "0x0c0b1e56a31d037280278327eb8fdfcc469a20213e5e65accf6e7c56af574449", "gas_used": 445, "gas_unit_price": 100, "sender": "9ec1cfa30b885a5c9d595f32f3381ec16d208734913b587be9e210f60be9f9ba", "sequence_number": 1, "success": true, "timestamp_us": 1735351754495208, "version": 273137362, "vm_status": "Executed successfully" }} ``` 3. View your message View your stored message by checking under Resources on the Explorer. 4. Celebrate! We did it! ## Next Steps [](#next-steps) Congratulations! You’ve successfully: 1. Compiled your first Move module 2. Added tests to help debug 3. Published your module on-chain 4. Used your contract through the CLI Now your published Move module can be connected to just like an API via one of our [many Official SDKs](/build/sdks)! Here are some **suggested next steps to get a deeper understanding of Move modules**: 1. Try modifying the module to add a new feature. You can use the [Move Book](https://aptos-labs.github.io/move-book/) to build your understanding of writing Move modules. 2. To understand how Move works on-chain, you can learn about Move’s [resource system](/network/blockchain/resources). 3. If you’re building an application to interact with contracts or look up data from on-chain, learn how to use the SDKs [here](/build/sdks). 4. Join the [Aptos Discord](https://discord.gg/aptoslabs) to connect with other developers. ## Supporting documentation [](#supporting-documentation) * [Account basics](/network/blockchain/accounts) * [TypeScript SDK](/build/sdks/ts-sdk) * [Python SDK](/build/sdks/python-sdk) * [REST API specification](/rest-api) # Accounts > Understand Aptos accounts, their addresses, authentication schemes, key rotation, sequence numbers, and how they control assets and resources on-chain. An account on Aptos controls a set of on-chain assets, including tokens and NFTs. These assets are represented by a Move language primitive called a **resource**, which enforces both access control and scarcity. Each account is identified by a 32-byte address. You can use the [Aptos Name Service](https://www.aptosnames.com/) to register human-readable `.apt` domains for key accounts. Unlike blockchains where accounts are implicit (just an address with a balance), Aptos accounts are explicit and backed by on-chain resources that enable features like key rotation and native multisig. However, with [Stateless Accounts (AIP-115)](/build/aips/aip-115), you no longer need to set up an account before using it. Any valid address is treated as an account by default, and you can send transactions as long as you hold the private key. The on-chain `Account` resource is created automatically only when first needed (for example, when rotating keys). See [Creating an account](#creating-an-account) for how addresses are derived. Aptos accounts offer features not available on most other networks: * **Key rotation.** The account’s authentication key can be changed to use a different private key, similar to changing a password. * **Native multisig.** Accounts support k-of-n multisig using Ed25519 and Secp256k1 ECDSA signature schemes. There are three types of accounts on Aptos: * _Standard account_ - This is a typical account corresponding to an address with a corresponding pair of public/private keys. * [_Resource account_](/build/smart-contracts/resource-accounts) - An autonomous account without a corresponding private key used by developers to store resources or publish modules on-chain. * [_Object_](/build/smart-contracts/objects) - A complex set of resources stored within a single address representing a single entity. ``` Alice: 0xeeff357ea5c1a4e7bc11b2b17ff2dc2dcca69750bfef1e1ebcaccf8c8018175bBob: 0x19aadeca9388e009d136245b9a67423f3eee242b03142849eb4f81a4a409e59c ``` ## Account address [](#account-address) Currently, Aptos supports only a single, unified identifier for an account. Accounts on Aptos are universally represented as a 32-byte hex string. A hex string shorter than 32-bytes is also valid; in those scenarios, the hex string can be padded with leading zeroes, e.g., `0x1` => `0x0000000000000...01`. While Aptos standards indicate leading zeroes may be removed from an Address, most applications attempt to eschew that legacy behavior and only support the removal of zeros for special addresses ranging from `0x0` to `0xa`. ## Creating an account [](#creating-an-account) When a user requests to create an account, for example, by using the [Aptos SDK](/build/sdks/ts-sdk/account), the following steps are executed: * Select the authentication scheme for managing the user’s account, e.g., Ed25519 or Secp256k1 ECDSA. * Generate a new private key, public key pair. * Combine the public key with the public key’s authentication scheme to generate a 32-byte authentication key and the account address. The user should use the private key for signing the transactions associated with this account. ## Account sequence number [](#account-sequence-number) The sequence number for an account indicates the number of transactions that have been submitted and committed on-chain from that account. Committed transactions either execute with the resulting state changes committed to the blockchain or abort wherein state changes are discarded and only the transaction is stored. Every transaction submitted must contain a unique sequence number for the given sender’s account. When the Aptos blockchain processes the transaction, it looks at the sequence number in the transaction and compares it with the sequence number in the on-chain account. The transaction is processed only if the sequence number is equal to or larger than the current sequence number. Transactions are only forwarded to other mempools or executed if there is a contiguous series of transactions from the current sequence number. Execution rejects out of order sequence numbers, preventing replay attacks of older transactions and guarantees ordering of future transactions. Aptos also supports [orderless transactions](/build/guides/orderless-transactions) which use a unique nonce instead of a sequence number. This enables parallel transaction submission from multiple machines without coordinating sequence numbers. See [AIP-123](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-123-orderless-transactions.md) for the full specification. ## Authentication key [](#authentication-key) The initial account address is set to the authentication key derived during account creation. However, the authentication key may subsequently change, for example, when you generate a new public-private key pair, public keys to rotate the keys. An account address never changes. The Aptos blockchain supports the following authentication schemes: 1. [Ed25519](https://ed25519.cr.yp.to/) 2. [Secp256k1 ECDSA](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-49.md) 3. [K-of-N multi-signatures](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-55.md) 4. A dedicated, now legacy, MultiEd25519 scheme ### Ed25519 authentication [](#ed25519-authentication) To generate an authentication key and the account address for an Ed25519 signature: 1. **Generate a key-pair**: Generate a fresh key-pair (`privkey_A`, `pubkey_A`). The Aptos blockchain uses the PureEdDSA scheme over the Ed25519 curve, as defined in RFC 8032. 2. **Derive a 32-byte authentication key**: Derive a 32-byte authentication key from the `pubkey_A`: ``` auth_key = sha3-256(pubkey_A | 0x00) ``` where `|` denotes concatenation. The `0x00` is the 1-byte single-signature scheme identifier. 3. Use this initial authentication key as the permanent account address. ### MultiEd25519 authentication [](#multied25519-authentication) With K-of-N multisig authentication, there are a total of N signers for the account, and at least K of those N signatures must be used to authenticate a transaction. To generate a K-of-N multisig account’s authentication key and the account address: 1. **Generate key-pairs**: Generate `N` ed25519 public keys `p_1`, …, `p_n`. 2. Decide on the value of `K`, the threshold number of signatures needed for authenticating the transaction. 3. **Derive a 32-byte authentication key**: Compute the authentication key as described below: ``` auth_key = sha3-256(p_1 | . . . | p_n | K | 0x01) ``` The `0x01` is the 1-byte multisig scheme identifier. 4. Use this initial authentication key as the permanent account address. ### Generalized authentication [](#generalized-authentication) Generalized authentication supports both Ed25519 and Secp256k1 ECDSA. Like the previous authentication schemes, these schemes contain a scheme value, `0x02` and `0x03` for single and multikey respectively, but also each key contains a prefix value to indicate its key type:
Key typePrefix byte
Ed25519 generalized scheme0x00
Secp256k1Ecdsa generalized scheme0x01
Secp256r1Ecdsa WebAuthn scheme0x02
Keyless0x03
For a single key Secp256k1 ECDSA account, using public key `pubkey`, the authentication key would be derived as follows: ``` auth_key = sha3-256(0x01 | pubkey | 0x02) ``` Where * the first entry, `0x01`, represents the use of a Secp256k1 ECDSA key; * the last entry, `0x02`, represents the authentication scheme. For a 1-of-2 multi-key account containing, a single Secp256k1 ECDSA public key, `pubkey_0`, and a single Ed25519 public key, `pubkey_1`, where one signature suffices, the authentication key would be derived as follows: ``` auth_key = sha3-256(0x02 | 0x01 | pubkey_0 | 0x00 | pubkey_1 | 0x01 | 0x03) ``` Where * the first entry, `0x02`, represents the total number of keys as a single byte; * the second-to-last entry, `0x01`, represents the required number of signatures as a single byte; * the last entry, `0x03`, represents the authentication scheme. ## Rotating the keys [](#rotating-the-keys) An Account on Aptos can rotate keys so that potentially compromised keys cannot be used to access the accounts. Keys can be rotated via the `account::rotate_authentication_key` function. Refreshing the keys is generally regarded as good hygiene in the security field. However, this presents a challenge for system integrators who are used to using a mnemonic to represent both a private key and its associated account. To simplify this for the system integrators, Aptos provides an on-chain mapping via aptos account lookup-address. The on-chain data maps an effective account address as defined by the current mnemonic to the actual account address. For more information, see [`account.move`](https://github.com/aptos-labs/aptos-core/blob/a676c1494e246c31c5e96d3363d99e2422e30f49/aptos-move/framework/aptos-framework/sources/account.move#L274). ## State of an account [](#state-of-an-account) The state of each account comprises both the code (Move modules) and the data (Move resources). An account may contain an arbitrary number of Move modules and Move resources: * **Move modules**: Move modules contain code, for example, type and procedure declarations; but they do not contain data. A Move module encodes the rules for updating the Aptos blockchain’s global state. * **Move resources**: Move resources contain data but no code. Every resource value has a type declared in a module published on the Aptos blockchain. ## Access control with signers [](#access-control-with-signers) The sender of a transaction is represented by a signer. When a function in a Move module takes `signer` as an argument, the Aptos Move VM translates the identity of the account that signed the transaction into a signer in a Move module entry point. See the below Move example code with `signer` in the `initialize` and `withdraw` functions. When a `signer` is not specified in a function, for example, the below `deposit` function, then no signer-based access controls will be provided for this function: ``` module Test::Coin { struct Coin has key { amount: u64 } public fun initialize(account: &signer) { move_to(account, Coin { amount: 1000 }); } public fun withdraw(account: &signer, amount: u64): Coin acquires Coin { let balance = &mut borrow_global_mut(Signer::address_of(account)).amount; *balance = *balance - amount; Coin { amount } } public fun deposit(account: address, coin: Coin) acquires Coin { let balance = &mut borrow_global_mut(account).amount; *balance = *balance + coin.amount; Coin { amount: _ } = coin; }} ``` # Transactions and States > Understand how transactions modify the blockchain state on Aptos, including transaction types, execution states, and the versioned database model. The Aptos blockchain stores three types of data: * **Transactions**: Transactions represent an intended operation being performed by an account on the blockchain (e.g., transferring assets). * **States**: The (blockchain ledger) state represents the accumulation of the output of execution of transactions, the values stored within all [resources](/network/blockchain/resources). * [**Events**](/network/blockchain/events): Ancillary data published by the execution of a transaction. ## Transactions [](#transactions) Aptos transactions contain information such as the sender’s account address, authentication from the sender, the desired operation to be performed on the Aptos blockchain, and the amount of gas the sender is willing to pay to execute the transaction. ### Transaction states [](#transaction-states) A transaction may end in one of the following states: * Committed on the blockchain and executed. This is considered as a successful transaction. * Committed on the blockchain and aborted. The abort code indicates why the transaction failed to execute. * Discarded during transaction submission due to a validation check such as insufficient gas, invalid transaction format, or incorrect key. * Discarded after transaction submission but before attempted execution. This could be caused by timeouts or insufficient gas due to other transactions affecting the account. The sender’s account will be charged gas for any committed transactions. During transaction submission, the submitter is notified of successful submission or a reason for failing validations otherwise. A transaction that is successfully submitted but ultimately discarded may have no visible state in any accessible Aptos node or within the Aptos network. A user can attempt to resubmit the same transaction to re-validate the transaction. If the submitting node believes that this transaction is still valid, it will return an error stating that an identical transaction has been submitted. The submitter can try to increase the gas cost by a trivial amount to help make progress and adjust for whatever may have been causing the discarding of the transaction further downstream. ### Contents of a Transaction [](#contents-of-a-transaction) A signed transaction on the blockchain contains the following information: * **Signature**: The sender uses a digital signature to verify that they signed the transaction (i.e., authentication). * **Sender address**: The sender’s [account address](/network/blockchain/accounts#account-address). * **Sender public key**: The public authentication key that corresponds to the private authentication key used to sign the transaction. * **Payload**: Indicates an action or set of actions Alice’s behalf. In the case this is a Move function, it directly calls into Move bytecode on the chain. Alternatively, it may be Move bytecode peer-to-peer [transaction script](/network/glossary#transaction-script). It also contains a list of inputs to the function or script. For this example, it is a function call to transfer an amount of Aptos Coins from Alice account to Bob’s account, where Alice’s account is implied by sending the transaction and Bob’s account and the amount are specified as transaction inputs. * [**Gas unit price**](/network/glossary#gas-unit-price): The amount the sender is willing to pay per unit of gas, to execute the transaction. This is represented in [Octas](/network/glossary#octa). * [**Maximum gas amount**](/network/glossary#maximum-gas-amount): The [maximum gas amount](/network/blockchain/gas-txn-fee#specifying-gas-fees-within-a-transaction) in APT the sender is willing to pay for this transaction. Gas charges are equal to the base gas cost covered by computation and IO multiplied by the gas price. Gas costs also include storage with an APT-fixed priced storage model. This is represented as [Octas](/network/glossary#octa). * **Gas price** (in specified gas units): This is the amount the sender is willing to pay per unit of [gas](/network/blockchain/gas-txn-fee) to execute the transaction. [Gas](/network/blockchain/gas-txn-fee) is a way to pay for computation and storage. A gas unit is an abstract measurement of computation with no inherent real-world value. * **Sequence number**: This is an unsigned integer that must be equal to the sender’s account [sequence number](/network/blockchain/accounts#account-sequence-number) at the time of execution. * **Expiration time**: A timestamp after which the transaction ceases to be valid (i.e., expires). ### Types of transaction payloads [](#types-of-transaction-payloads) Within a given transaction, the two most common types of payloads include: * An entry point * [A script (payload)](/build/smart-contracts/scripts) Currently, the SDKs [Python](/build/sdks/python-sdk) and [Typescript](/build/sdks/ts-sdk) support both. This guide points out many of those entry points, such as `coin::transfer` and `aptos_account::create_account`. All operations on the Aptos blockchain should be available via entry point calls. While one could submit multiple transactions calling entry points in series, many such operations may benefit from being called atomically from a single transaction. A script payload transaction can call any entry point or public function defined within any module. ## States [](#states) The Aptos blockchain’s ledger state, or global state, represents the state of all accounts in the Aptos blockchain. Each validator node in the blockchain must know the latest version of the global state to execute any transaction. Anyone can submit a transaction to the Aptos blockchain to modify the ledger state. Upon execution of a transaction, a transaction output is generated. A transaction output contains zero or more operations to manipulate the ledger state called **write sets** emitting a vector of resulting events, the amount of gas consumed, and the executed transaction status. ### Proofs [](#proofs) The Aptos blockchain uses proof to verify the authenticity and correctness of the blockchain data. Data within the Aptos blockchain is replicated across the network. Each validator and fullnode’s [storage](/network/blockchain/validator-nodes#storage) is responsible for persisting the agreed upon blocks of transactions and their execution results to the database. The blockchain is represented as an ever-growing [Merkle tree](/network/glossary#merkle-trees), where each leaf appended to the tree represents a single transaction executed by the blockchain. All operations executed by the blockchain and all account states can be verified cryptographically. These cryptographic proofs ensure that: * The validator nodes agree on the state. * The client does not need to trust the entity from which it is receiving data. For example, if a client fetches the last **n** transactions from an account, a proof can attest that no transactions were added, omitted or modified in the response. The client may also query for the state of an account, ask whether a specific transaction was processed, and so on. ### Versioned database [](#versioned-database) The ledger state is versioned using an unsigned 64-bit integer corresponding to the number of transactions the system has executed. This versioned database allows the validator nodes to: * Execute a transaction against the ledger state at the latest version. * Respond to client queries about ledger history at both current and previous versions. ## Transactions change ledger state [](#transactions-change-ledger-state) ![Signed Transaction Flow](/_astro/transactions-and-state.DnHxozEu.svg) ![Signed Transaction Flow](/_astro/transactions-and-state-dark.ffwcWBtN.svg) The above figure shows how executing transaction T_i_ changes the state of the Aptos blockchain from S_i-1_ to S_i_. In the figure: * Accounts **A** and **B**: Represent Alice’s and Bob’s accounts on the Aptos blockchain. * **S_i-1_** : Represents the (_i-1_)-the state of the blockchain. In this state, Alice’s account **A** has a balance of 110 APT (Aptos coins), and Bob’s account **B** has a balance of 52 APT. * **T_i_** : This is the _i_\-th transaction executed on the blockchain. In this example, it represents Alice sending 10 APT to Bob. * **Apply()**: This is a deterministic function that always returns the same final state for a specific initial state and a specific transaction. If the current state of the blockchain is **S_i-1_**, and transaction **T_i_** is executed on the state **S_i-1_**, then the new state of the blockchain is always **S_i_**. The Aptos blockchain uses the [Move language](https://aptos-labs.github.io/move-book/) to implement the deterministic execution function **Apply()**. * **S_i_** : This is the _i_\-the state of the blockchain. When the transaction **T_i_** is applied to the blockchain, it generates the new state **S_i_** (an outcome of applying **Apply(S_i-1_, T_i_)** to **S_i-1_** and **T_i_**). This causes Alice’s account balance to be reduced by 10 to 100 APT and Bob’s account balance to be increased by 10 to 62 APT. The new state **S_i_** shows these updated balances. ## Size limits [](#size-limits) As part of the gas schedule, there are on-chain configurable limits for the sizes of [the transaction itself](https://github.com/aptos-labs/aptos-core/blob/8074588b5c9c4424fa247c2c9ec5572981ee31cd/aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs#L71-L81) and [its outputs](https://github.com/aptos-labs/aptos-core/blob/8074588b5c9c4424fa247c2c9ec5572981ee31cd/aptos-move/aptos-gas-schedule/src/gas_schedule/transaction.rs#L152-L177).
Limit TypeCurrent Per Transaction Limit
transaction64KB
governance transaction1MB
a single write op1MB
all write ops combined10MB
number of write ops8192
a single event1MB
all events combined10MB
# SDKs Overview > Comprehensive software development kits for building on Aptos blockchain in TypeScript, Python, Go, Rust, C#, C++, Unity and more languages ## Official SDKs [](#official-sdks) Use these Aptos software development kits (SDKs), in combination with the [Aptos CLI](/build/cli) for your development on the Aptos blockchain. [Typescript SDK](/build/sdks/ts-sdk) Aptos Typescript SDK (recommended) [Python SDK](/build/sdks/python-sdk) Aptos Python SDK [Go SDK](/build/sdks/go-sdk) Aptos Go SDK [C#/.NET SDK](/build/sdks/dotnet-sdk) Aptos .NET SDK [Rust SDK](/build/sdks/rust-sdk) Aptos Rust SDK [C++ / Unreal SDK](/build/sdks/cpp-sdk) Aptos C++ / Unreal SDK [Unity SDK](/build/sdks/unity-sdk) Aptos Unity SDK [Wallet Adapter](/build/sdks/wallet-adapter) Aptos Wallet Adapter [Forklift](/build/sdks/forklift) Testing & scripting framework for Move contracts with Network Forking support ## [Community SDKs](/build/sdks/community-sdks) [](#community-sdks) SDKs provided by the community for Aptos. These may not be fully vetted by the Aptos team, and may still be in development. They are still provided as a resource for all developers. [Kotlin SDK](/build/sdks/community-sdks/kotlin-sdk) Aptos Kotlin Multiplatform SDK by Kaptos [Swift SDK](/build/sdks/community-sdks/swift-sdk) Aptos Swift SDK by Alcove # 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. 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 [](#-install-the-aptos-cli) [Mac](/build/cli/install-cli/install-cli-mac) Install Aptos CLI via homebrew [Windows](/build/cli/install-cli/install-cli-windows) Install Aptos CLI on Windows via powershell script or pre-compiled binary [Linux](/build/cli/install-cli/install-cli-linux) Install Aptos CLI on Linux via shell script or pre-compiled binary [Advanced (Install Specific Versions)](/build/cli/install-cli/install-cli-specific-version) Build a specific version of the Aptos CLI from source ## ⚙️ Setup the Aptos CLI [](#️-setup-the-aptos-cli) [Setup the CLI](/build/cli/setup-cli) Setup and configure the Aptos CLI [Advanced (Move Prover)](/build/cli/setup-cli/install-move-prover) Setup and install the Move Prover ## 🛠️ Using the Aptos CLI [](#️-using-the-aptos-cli) [Move Contracts](/build/cli/working-with-move-contracts) Compile, Publish, Simulate, and Benchmark Move Contracts [Trying things On-chain](/build/cli/trying-things-on-chain) Interact with Aptos, create accounts, query accounts, use a hardware device like Ledger [Running a Local Network](/build/cli/running-a-local-network) Run a local node / network # Smart Contracts > Learn to write secure, efficient smart contracts on Aptos using the Move programming language with examples, tutorials, and developer resources Aptos contracts are written using Move, a next generation language for secure, sandboxed, and formally verified programming which is used for multiple chains. Move allows developers to write programs that flexibly manage and transfer assets while providing security and protections against attacks on those assets. ## 📖 Learn Move [](#-learn-move) [Why Move?](/build/smart-contracts/why-move) Learn why Aptos uses the Move Language [Create Package](/build/smart-contracts/create-package) Get started by learning how to create a Move package [Objects](/build/smart-contracts/objects) Learn how to use the Object standard on Aptos to create composable and flexible primitives on chain ## 👨‍💻 Move Examples [](#-move-examples) [Aptos Move Examples](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples) 30+ examples on how to develop Move on Aptos [Move Tutorial](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/move-tutorial) Covers the basics of programming with Move [Your first Move Module](/build/guides/first-move-module) A example of how to publish your first move module Here is a `hello_blockchain` example of move hello\_blockchain.move ``` module hello_blockchain::message { use std::error; use std::signer; use std::string; use aptos_framework::event; //:!:>resource struct MessageHolder has key { message: string::String, } //<:!:resource #[event] struct MessageChange has drop, store { account: address, from_message: string::String, to_message: string::String, } /// There is no message present const ENO_MESSAGE: u64 = 0; #[view] public fun get_message(addr: address): string::String acquires MessageHolder { assert!(exists(addr), error::not_found(ENO_MESSAGE)); borrow_global(addr).message } public entry fun set_message(account: signer, message: string::String) acquires MessageHolder { let account_addr = signer::address_of(&account); if (!exists(account_addr)) { move_to(&account, MessageHolder { message, }) } else { let old_message_holder = borrow_global_mut(account_addr); let from_message = old_message_holder.message; event::emit(MessageChange { account: account_addr, from_message, to_message: copy message, }); old_message_holder.message = message; } } #[test(account = @0x1)] public entry fun sender_can_set_message(account: signer) acquires MessageHolder { let addr = signer::address_of(&account); aptos_framework::account::create_account_for_test(addr); set_message(account, string::utf8(b"Hello, Blockchain")); assert!( get_message(addr) == string::utf8(b"Hello, Blockchain"), ENO_MESSAGE ); }} ``` ## ⚒️ Developer Resources [](#️-developer-resources) ### FAQ and Discussions [](#faq-and-discussions) * [Aptos Dev Discussions](https://github.com/aptos-labs/aptos-developer-discussions/discussions) for Q&A about Move. ### Move IDE plugins [](#move-ide-plugins) * Move on Aptos extension for [VSCode](https://marketplace.visualstudio.com/items?itemName=AptosLabs.move-on-aptos) and [OpenVSX](https://open-vsx.org/extension/aptoslabs/move-on-aptos). * [Move language plugin for JetBrains IDEs](https://plugins.jetbrains.com/plugin/14721-move-language) ### External Resources [](#external-resources) * [Aptos Move by Example](https://move-developers-dao.gitbook.io/aptos-move-by-example) * [Teach yourself Move on Aptos](https://github.com/econia-labs/teach-yourself-move). * [Formal Verification, the Move Language, and the Move Prover](https://www.certik.com/resources/blog/2wSOZ3mC55AB6CYol6Q2rP-formal-verification-the-move-language-and-the-move-prover) * [Collection of nestable Move resources](https://github.com/taoheorg/taohe) We have a new Move on Aptos compiler that supports Move 2. See [this page](/build/smart-contracts/compiler_v2) for more information. # Building with Objects > Learn about objects for Aptos Objects in smart contract development. In Move, Objects group resources together so they can be treated as a single entity on chain. Objects have their own address and can own resources similar to an account. They are useful for representing more complicated data types on-chain as Objects can be used in entry functions directly, and can be transferred as complete packages instead of one resource at a time. Here’s an example of creating an Object and transferring it: ``` module my_addr::object_playground { use std::signer; use std::string::{Self, String}; use aptos_framework::object::{Self, ObjectCore}; struct MyStruct1 has key { message: String, } struct MyStruct2 has key { message: String, } entry fun create_and_transfer(caller: &signer, destination: address) { // Create object let caller_address = signer::address_of(caller); let constructor_ref = object::create_object(caller_address); let object_signer = object::generate_signer(&constructor_ref); // Set up the object by creating 2 resources in it move_to(&object_signer, MyStruct1 { message: string::utf8(b"hello") }); move_to(&object_signer, MyStruct2 { message: string::utf8(b"world") }); // Transfer to destination let object = object::object_from_constructor_ref( &constructor_ref ); object::transfer(caller, object, destination); }} ``` During construction, Objects can be configured to be transferrable and extensible. For example, you could use an Object to represent a soulbound NFT by making it only transferrable once, and have it own resources for an image link and metadata. Objects can also own other Objects, so you could implement your own NFT collection Object by transferring several of the soulbound NFTs to it. ## Learn how to [](#learn-how-to) * [Create and configure a new Object.](/build/smart-contracts/object/creating-objects) * [Use Objects you created.](/build/smart-contracts/object/using-objects) ## Examples with Object contracts [](#examples-with-object-contracts) * [Digital Asset Marketplace Example](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/marketplace) * [Digital Assets Examples](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/token_objects) * [Fungible Asset Examples](https://github.com/aptos-labs/aptos-core/tree/main/aptos-move/move-examples/fungible_asset) # Randomness API > Learn about randomness for Move smart contract development on Aptos blockchain. ## What does it do: a quick example [](#what-does-it-do-a-quick-example) ### How random numbers have been obtained, insecurely/awkwardly [](#how-random-numbers-have-been-obtained-insecurelyawkwardly) Building a lottery system and pick a random winner from `n` participants is trivial, at least in the centralized world with a trusted server: the backend simply calls a random integer sampling function (`random.randint(0, n-1)` in python, or `Math.floor(Math.random() * n)` in JS). Unfortunately, without an equivalent of `random.randint()` in Aptos Move, building a dApp version of it was actually much harder. One may have written a contract where the random numbers are sampled insecurely (e.g., from the blockchain timestamp): ``` module module_owner::lottery { // ... struct LotteryState { players: vector
, winner_idx: std::option::Option, } fun load_lottery_state_mut(): &mut LotteryState { // ... } entry fun decide_winner() { let lottery_state = load_lottery_state_mut(); let n = std::vector::length(&lottery_state.players); let winner_idx = aptos_framework::timestamp::now_microseconds() % n; lottery_state.winner_idx = std::option::some(winner_idx); }} ``` The implementation above is insecure in multiple ways: * a malicious user may bias the result by picking the transaction submission time; * a malicious validator can bias the result easily by selecting which block the `decide_winner` transaction goes to. Other dApps may have chosen to use an external secure randomness source (e.g., [drand](https://drand.love/)), which is typically a complicated flow: 1. The participants agree on using a future randomness seed promised by the randomness source to determine the winner. 2. Once the randomness seed is revealed, the clients fetch it and derive the winner locally. 3. One of the participants submits the seed and the winner on chain. ``` module module_owner::lottery { // ... struct LotteryState { players: vector
, /// public info about the "future randomness", tyipcally a VRF public key and an input. seed_verifier: vector, winner_idx: std::option::Option, } fun load_lottery_state_mut(): &mut LotteryState { // ... } fun is_valid_seed(seed_verifier: vector, seed: vector): bool { // ... } fun derive_winner(n: u64, seed: vector): u64 { // ... } entry fun update_winner(winner_idx: u64, seed: vector) { let lottery_state = load_lottery_state_mut(); assert!(is_valid_seed(lottery_state.seed_verifier, seed), ERR_INVALID_SEED); let n = std::vector::length(players); let expected_winner_idx = derive_winner(n, seed); assert!(expected_winner_idx == winner_idx, ERR_INCORRECT_DERIVATION); lottery_state.winner_idx = std::option::some(winner_idx); }} ``` ### Achieve simplicity + security with Aptos randomness API [](#achieve-simplicity--security-with-aptos-randomness-api) Using Aptos randomness API, the implementation will look like this: ``` module module_owner::lottery { // ... use aptos_framework::randomness; struct LotteryState { players: vector
, winner_idx: std::option::Option, } fun load_lottery_state_mut(): &mut Lottery { // ... } #[randomness] entry fun decide_winner() { let lottery_state = load_lottery_state_mut(); let n = vector::length(&lottery_state.players); let winner_idx = aptos_framework::randomness::u64_range(0, n); lottery_state.winner_idx = std::option::some(winner_idx); }} ``` where: * `let winner_idx = aptos_framework::randomness::u64_range(0, n);` is the randomness API call that returns an u64 integer in range `[0, n)` uniformly at random. * `#[randomness]` is a required attribute to enable the API call at runtime. ## How to use Aptos randomness API [](#how-to-use-aptos-randomness-api) ### Prerequisites [](#prerequisites) Ensure you have the latest [aptos-cli](/build/cli) installed. ### Keep undergasing attacks in mind [](#keep-undergasing-attacks-in-mind) Caution **The randomness API currently does not prevent undergasing attacks.** Carefully read the undergasing section to understand about undergasing attacks and how to prevent them. As a dApp developer, you will need to design applications using randomness with safety in mind. ### Identify randomness-dependent entry functions and make them compliant [](#identify-randomness-dependent-entry-functions-and-make-them-compliant) For safety (discussed with more details later), randomness API calls are only allowed from an entry function that is: * private, and * annotated with `#[randomness]`. It’s now a good time to think about what user actions need randomness API, write them down, and make sure they are private and have the right attribute, as shown in the example below. ``` module module_owner::lottery { // ... #[randomness] entry fun decide_winner() { // ... }} ``` At runtime, when randomness API is called, the VM checks whether the outermost of the callstack is a private entry function with `#[randomness]` attribute. **If not, the entire transaction is aborted.** ### Call the API [](#call-the-api) The APIs are public functions under `0x1::randomness` and can be referenced directly, as demonstrated in the lottery example above. ``` module module_owner::lottery { // ... use aptos_framework::randomness; #[randomness] entry fun decide_winner() { // ... let winner_idx = aptos_framework::randomness::u64_range(0, n); lottery_state.winner_idx = std::option::some(winner_idx); }} ``` The above example uses function `u64_range()` but many other basic types are also supported. Here’s a quick overview of all the API, where `T` can be one of `u8, u16, u32, u64, u128, u256`. ``` module aptos_framework::randomness { /// Generates an number uniformly at random. fun u8_integer(): u8 {} /// Generates an number uniformly at random. fun u16_integer(): u16 {} // fun u32_integer(), fun u64_integer() ... /// Generates a number `[min_incl, max_excl)` uniformly at random. fun u8_range(min_incl: u8, max_excl: u8): u8 {} /// Generates a number `[min_incl, max_excl)` uniformly at random. fun u16_range(min_incl: u16, max_excl: u16): u16 {} // fun u32_range(), fun u64_range() ... /// Generates a sequence of bytes uniformly at random /// n is the number of bytes /// If n is 0, returns the empty vector. fun bytes(n: u64): vector {} /// Generate a permutation of `[0, 1, ..., n-1]` uniformly at random. /// n is the number of bytes /// If n is 0, returns the empty vector. fun permutation(n: u64): vector {}} ``` The full API function list and documentation can be found [here](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-framework/doc/randomness.md). ## Security considerations [](#security-considerations-1) Randomness API is powerful in many ways: it unlocks new dApp designs; but if used incorrectly, it may leave your dApps open to attacks! Below are some common mistakes you should avoid. ### Randomness API calls in public functions [](#randomness-api-calls-in-public-functions) As your dApp gets more complicated, you may have multiple entry functions that need to share the same randomness-dependent logic, and want to pull the logic out as a separate helper function. While this is supported as shown below, extra care must be taken. ``` module module_owner::lottery { // ... use aptos_framework::randomness; #[randomness] entry fun decide_winner_v0() { // ... decide_winner_internal(lottery_state); } #[randomness] entry fun decide_winner_v1() { // ... decide_winner_internal(lottery_state); } // A private helper function fun decide_winner_internal(lottery_state: &mut lottery_state) { let n = std::vector::length(&lottery_state.players); let winner_idx = aptos_framework::randomness::u64_range(0, n); lottery_state.winner_idx = std::option::some(winner_idx); }} ``` If `decide_winner_internal()` were accidentally marked public, malicious players can deploy their own contract to: 1. call`decide_winner_internal()`; 2. read the lottery result (assuming the `lottery` module has some getter functions for the result); 3. abort if the result is not in their favor. By repeatedly calling their own contract until a txn succeeds, malicious users can bias the uniform distribution of the winner (dApp developer’s initial design). This is referred to as a [test-and-abort attack](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-41.md#test-and-abort-attacks). The Aptos Move compiler has been updated to prevent this attack for your contract safety: a randomness-dependent public function is treated as a compile error. If you have finished the steps in the [“build Aptos CLI”](/build/cli) section, then your Aptos CLI are equipped with the updated compiler. ``` module module_owner::lottery { // Compile error! public fun decide_winner_internal(lottery_state: &mut lottery_state) { let n = std::vector::length(&lottery_state.players); let winner_idx = aptos_framework::randomness::u64_range(0, n); lottery_state.winner_idx = std::option::some(winner_idx); }} ``` Not recommended, but if you intend to expose such a randomness-dependent function to the public, you can bypass the compiler check by annotating your function with `#[lint::allow_unsafe_randomness]`. ``` module module_owner::lottery { // Can compile, but use it at your own risk! #[lint::allow_unsafe_randomness] public fun decide_winner_internal(lottery_state: &mut lottery_state) { let n = std::vector::length(&lottery_state.players); let winner_idx = aptos_framework::randomness::u64_range(0, n); lottery_state.winner_idx = std::option::some(winner_idx); }} ``` ### Undergasing attacks, and how to prevent [](#undergasing-attacks-and-how-to-prevent) Imagine such a dApp. It defines a private entry function for a user to: 1. toss a coin (gas cost: 9), then 2. get a reward (gas cost: 10) if coin=1, or do some cleanup (gas cost: 100) otherwise. A malicious user can control its account balance, so it covers at most 108 gas units (or set transaction parameter `max_gas=108`), and the cleanup branch (total gas cost: 110) will always abort with an out-of-gas error. The user then repeatedly call the entry function until it gets the reward. Formally, this is referred to as an [undergasing attack](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-41.md#undergasing-attacks), where an attacker can control how much gas is left for the entry function to execute, and so can arbitrarily decide to abort paths that cost more gas, biasing the outcome (i.e., effectively changing the distribution of random numbers). Caution **WARNING: randomness API currently does not prevent undergasing attacks.** As a dApp developer, you need to be very careful in your design to avoid this type of attack. Here are some ideas of how to prevent undergasing attack generally. * Make your entry function gas independent from the randomness outcome. The simplest example is to not “act” on the randomness outcome, i.e., read it and store it for later. Note that calling any other functions can have variable gas costs. For example, when calling randomness to decide which player should win, and then depositing the winnings to the winner might seem like a fixed gas cost. But, `0x1::coin::transfer` / `0x1::fungible_asset::transfer` can have a variable cost based on the user’s on-chain state. * If your dApp involves a trusted admin/admin group, only allow the trusted to execute randomness transaction (i.e., require an admin signer). * Make the path that is most beneficial have the highest gas (as attacker can only abort paths with gas above a threshold he chooses. NOTE: that this can be tricky to get right, and gas schedule can change, and is even harder to get right when there are more than 2 possible outcomes. Note that everything that does not fall in above categories can be susceptible to undergasing attack in a subtle ways. Reach out if you need help. We will be providing more functionality in the future, to allow for more complex code to be able to be safe against undergasing attacks. ### It’s random, but not a secret [](#its-random-but-not-a-secret) While the randomness API mimics the standard libraries you use to implement a private centralized server, keep in mind that **the seed is public, and so is your transaction execution**, and not every randomness-dependent logic in your private centralized server can be transferred on chain safely, **especially when it involves a secret that only the server should see**. For example, in your contract, DO NOT try to do the following. * Use randomness API to generate an asymmetric key pair, discard the private key, then think the public key is safe. * Use randomness API to shuffle some opened cards, veil them, and think no one knows the permutation. ## Read more [](#read-more) [Aptogotchi Random Mint](https://github.com/aptos-labs/aptogotchi-random-mint/tree/main) is an official demo dApp built to demonstrate the use of randomness API. The full API function list and documentation can be found [here](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-framework/doc/randomness.md). You can also find the partial implementation of the API functions and example unit tests [here](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-framework/sources/randomness.move). See [AIP-41](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-41.md) for the API design, and [AIP-79](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-79.md) if you are interested in system-level/cryptography details. # Aptos APIs > Access the Aptos blockchain through various APIs including REST API, GraphQL, and specialized endpoints for different use cases The Aptos Blockchain network can be accessed by several APIs, depending on your use-case. ## Aptos Fullnode [](#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. [Aptos Fullnode REST API (Mainnet)](/build/apis/fullnode-rest-api?network=mainnet) Mainnet API playground for Aptos Fullnode REST API [Aptos Fullnode REST API (Testnet)](/build/apis/fullnode-rest-api?network=testnet) Testnet API playground for Aptos Fullnode REST API [Aptos Fullnode REST API (Devnet)](/build/apis/fullnode-rest-api?network=devnet) Devnet API playground for Aptos Fullnode REST API ## Indexer [](#indexer) [Indexer GraphQL API](/build/indexer) This GraphQL API offers a high-level, opinionated GraphQL interface to read state from the Aptos Blockchain. It's ideal for interacting with NFTs, Aptos Objects, or custom Move contracts. Learn more about the Indexer-powered GraphQL API here. [Transaction Stream API](/build/indexer/txn-stream) This GRPC API streams historical and real-time transaction data to an indexing processor. It's used by Aptos Core Indexing and can also support custom app-specific indexing processors for real-time blockchain data processing. Learn more here. ## Faucet (Only Testnet/Devnet) [](#faucet-only-testnetdevnet) [Faucet API](/build/apis/faucet-api) This API provides the ability to receive test tokens on devnet. Its primary purpose is the development and testing of applications and Move contracts before deploying them to mainnet. On testnet you can mint at the mint page. 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-operated-api-deployments) [Aptos Labs](https://aptoslabs.com) operates a deployment of these APIs on behalf of [Aptos Foundation](https://aptosnetwork.com/foundation) 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. # Fullnode REST API > Low-level REST API for reading state, submitting transactions, and simulating operations on the Aptos blockchain 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 [](#fullnode-rest-api-explorer) [Mainnet Fullnode REST API](https://fullnode.mainnet.aptoslabs.com/v1/spec#/) REST API Explorer for Mainnet [Testnet Fullnode REST API](https://fullnode.testnet.aptoslabs.com/v1/spec#/) REST API Explorer for Testnet [Devnet Fullnode REST API](https://fullnode.devnet.aptoslabs.com/v1/spec#/) REST API Explorer for Devnet ## Understanding rate limits [](#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 [](#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 [](#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: ``` 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: ``` 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. # Exchange Integration Guide > Comprehensive guide for integrating Aptos and its assets into cryptocurrency exchanges with balance tracking and testing. This describes how to integrate Aptos and Aptos assets into an exchange. It provides generic information for tracking balances, transferring assets, and testing the integration. ## Overview [](#overview) This document will guide you through the following tasks to integrate with Aptos: * Infrastructure * Address standards * Asset standards * Retrieving balances * Tracking balance changes * Transferring assets * Testing the integration ## Infrastructure [](#infrastructure) It’s suggested that you run your own [full node](/network/nodes/full-node) to interact with the Aptos blockchain. This will allow you to query the blockchain for the latest state and submit transactions. You can also use the [Indexer](/build/indexer) to query for on-chain data efficiently. ## Address Standards [](#address-standards) ### Addresses [](#addresses) A single address can be represented in three ways. We recommend you show all leading zeros, and the `0x`. Here is an example of all three representations for the framework address `0x1`: * `0x00000000000000000000000000000001` - A full representation of 32-bytes in hex with a leading `0x`. This is preferred. * `0x1` - The short representation of the address with a leading `0x`. This is kept around for compatibility, but preferred with all leading 0s. * `00000000000000000000000000000001` - A full representation of 32-bytes in hex without a leading `0x`. This is kept around for compatibility, but preferred with leading 0x. For example SDKs will handle this parsing automatically, and we suggest you use the SDKs directly to handle it for you. ``` import { AccountAddress } from "@aptos-labs/ts-sdk";const address = AccountAddress.from("0x1");address.toStringLong(); // 0x00000000000000000000000000000001 ``` There is additionally, Aptos Name Service (ANS) for friendly .apt names. For more information about addresses and Aptos Names, see our page on [Accounts](/network/blockchain/accounts). ## Account Standards [](#account-standards) Accounts must exist prior to sending a transaction to the blockchain. This is done by creating an account resource, which can be created by simply calling `0x1::aptos_account::transfer` with a zero amount to the account you want to create. Optionally, `0x1::aptos_account::create_account` can be used to create an account with a zero balance. ``` import { Aptos, Ed25519Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk"; const aptos = new Aptos();const account = new Ed25519Account({privateKey: new Ed25519PrivateKey("private key")})const transaction = await aptos.transferCoinTransaction({sender: account.accountAddress, recipient: "receiver address", amount: 100000000})const pendingTransaction = await aptos.transaction.signAndSubmitTransaction({signer: account, transaction})const committedTransaction = await aptos.waitForTransaction({transactionHash: pendingTransaction.hash}); ``` ## Asset Standards [](#asset-standards) Aptos provides two standards for fungible tokens, similar to ERC-20 tokens on Ethereum: * An earlier [Coin standard](/build/smart-contracts/aptos-coin) used by assets on Aptos. * A newer [Fungible Asset Standard](/build/smart-contracts/fungible-asset) which is more featured. Additionally, there is a migratory period for assets from Coin to Fungible Asset standards. We will call this from now on **migrated coins**. Migrated coins may have two forms, but either can be used interchangeably with Coin standards. This is important to note when querying balances, to use coin functions and not fungible asset functions. The FA standard can only deal with the FA form. ### Coin Standard (tl;dr) [](#coin-standard-tldr) A **coin** has an associated contract that holds the on-chain struct that represents the coin. The coin is represented as a struct name e.g. `0x1::aptos_coin::AptosCoin` for `APT`. All coins are stored in an account resource called `0x1::coin::CoinStore`. Coins must be registered prior to using the `CoinStore`, but if using the proper functions e.g. `0x1::aptos_account::transfer` or `0x1::aptos_account::transfer_coins`, this will be done automatically. Coins can be _migrated_ to a fungible asset. In order to support a migrated asset, continue calling the coin functions as will be mentioned later. More info can be found at: [Coin Standard](/build/smart-contracts/aptos-coin) ### Fungible Asset Standard (tl;dr) [](#fungible-asset-standard-tldr) A **fungible asset** has an associated metadata address that holds the metadata for the fungible asset. This is commonly called the fa metadata address. The asset is represented as an address e.g. `0xA` for `APT`. All fungible assets are stored in an `object`, which is called a `fungible asset store`. For exchanges, the most important store is `primary_fungible_store`, which is the default store for fungible assets. This is directly connected to an owner. From this point on in this guide, we will only talk about supporting `primary_fungible_store` for fungible assets. More info can be found at: [Fungible Asset Standard](/build/smart-contracts/fungible-asset) ## Retrieving Balances [](#retrieving-balances) Retrieving current balances for assets are different for each standard. Integration is considered complete when it can handle both. Balances are always returned in their subunits. For example, `APT` is returned in `octas` (1e-8 APT). So, when an API returns a balance of `100000000`, this is `1 APT`. If it returns `100`, this is `0.000001 APT`. ### Coin (and migrated coins) Balances [](#coin-and-migrated-coins-balances) To retrieve the balance of a coin, or a coin that was migrated to a fungible asset, you can use the `0x1::coin::balance(account address)` view function. This will combine the coin and coin migrated to fungible asset balances. ``` import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk"; const config = new AptosConfig({ network: Network.DEVNET });const aptos = new Aptos(config); const coinType = "0x1::aptos_coin::AptosCoin";const account = "0x00000000000000000000000000000001";const [balanceStr] = await aptos.view<[string]>({ payload: { function: "0x1::coin::balance", typeArguments: [coinType], functionArguments: [account] }});const balance = parseInt(balanceStr, 10); ``` A specific ledger version (transaction height) can be provided to get the balance at that point in time. The below example shows for ledger version `1,000,000`. ``` import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk"; const config = new AptosConfig({ network: Network.DEVNET });const aptos = new Aptos(config); const coinType = "0x1::aptos_coin::AptosCoin";const account = "0x00000000000000000000000000000001";const [balanceStr] = await aptos.view<[string]>({ payload: { function: "0x1::coin::balance", typeArguments: [coinType], functionArguments: [account], options: { ledgerVersion: 1_000_000 } }});const balance = parseInt(balanceStr, 10); ``` ### Fungible Asset Balances [](#fungible-asset-balances) To retrieve the balance of a fungible asset, you can use the `0x1::primary_fungible_store::balance<0x1::object::ObjectCore>(account address, fungible asset metadata address)` view function. Note, that this will not include the balance of coins if it’s a migrated coin. ``` import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk"; const config = new AptosConfig({ network: Network.DEVNET });const aptos = new Aptos(config); const faMetadataAddress = "0xA";const account = "0x00000000000000000000000000000001";const [balanceStr] = await aptos.view<[string]>({ payload: { function: "0x1::primary_fungible_store::balance", typeArguments: ["0x1::object::ObjectCore"], functionArguments: [account, faMetadataAddress] }});const balance = parseInt(balanceStr, 10); ``` A specific ledger version (transaction height) can be provided to get the balance at that point in time. The below example shows for ledger version `1,000,000`. ``` import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk"; const config = new AptosConfig({ network: Network.DEVNET });const aptos = new Aptos(config); const faMetadataAddress = "0xA";const account = "0x00000000000000000000000000000001";const [balanceStr] = await aptos.view<[string]>({ payload: { function: "0x1::primary_fungible_store::balance", typeArguments: ["0x1::object::ObjectCore"], functionArguments: [account, faMetadataAddress] }, options: { ledgerVersion: 1_000_000 }});const balance = parseInt(balanceStr, 10); ``` Besides SDK, you can also directly use aptos node’s [balance API endpoint](/build/apis/fullnode-rest-api#tag/accounts/GET/accounts/%7Baddress%7D/balance/%7Basset_type%7D) to get the balance of a migrated coin or fungible asset. ## Tracking Balance Changes [](#tracking-balance-changes) Balance changes can be queried in one of two ways: 1. By watching for events that change the balance for each transaction. 2. By querying the indexer for indexed balance change events. In the past, it was able to use the `events` endpoint for an account to get the transactions that changed the balance. This is still possible, but will be deprecated in the future, and is not recommended for new integrations. ### Coin Balance Changes [](#coin-balance-changes) Coin balances are tracked as two items, write set changes, and events. Write set changes are end state of the coin balance, and events are the events that are emitted when a coin is withdrawn or deposited. Here is an [example of a coin transfer](https://explorer.aptoslabs.com/txn/1747361321?network=mainnet). The coin transfer can be tracked as an individual transaction [here](https://fullnode.mainnet.aptoslabs.com/v1/transactions/by_version/1747361321) from the REST API. We’ll break it down into a few parts: 1. The general transaction details tell information about the transaction. The most important thing here is the transaction version is `1747361321`. This gives us total order of all transactions on the blockchain. Think of it like block height, but for transactions. 2. The Write set `changes` are the end state of the transaction. It shows all resources that were modified by the transaction, and what it’s final state was. In this case, we only care about coin store changes. 3. Events are the events that were emitted by the transaction. In this case, we only care about the `0x1::coin::Withdraw` and `0x1::coin::Deposit` events. The Coin withdraw event is emitted when coins are withdrawn from an account. The account’s balance will decrease by that amount in the field `data.amount`. To determine the matching asset, you must match the `guid` in the `withdraw_events` to the `guid` in the `changes` section for a `CoinStore`. But if the `CoinStore` is not found in the `changes`, it means it got deleted, and a `CoinStoreDeleteEvent` must be present instead. Then you can match the `guid` with `deleted_withdraw_event_handle_creation_number` and `event_handle_creation_address`. The Coin deposit event is emitted when coins are deposited into an account. The account’s balance will increase by that amount in the field `data.amoount`. To determine the matching asset, you must match the `guid` in the `deposit_events` to the `guid` in the `changes` section for a `CoinStore`. Similarly, if the `CoinStore` is not found in the `changes`, it means it got deleted, and a `CoinStoreDeleteEvent` must be present instead. Then you can match the `guid` with `deleted_deposit_event_handle_creation_number` and `event_handle_creation_address`. 4. Gas usage only is tracked for APT. There is no direct event for tracking gas, but it can be calculated from the transaction. Using the `gas_used` field, and the `gas_unit_price` field, you can calculate the total gas used. In this case, the `gas_used` is `999` and the `gas_unit_price` is `100`, so the total gas deducted from the sender(`0x559d4f690c683fca7c539237aa8dc4c6ec09886b7016bf66f2cdeffef55468f0`) is `999 * 100 = 99900 subunits` Remember that the subunits are used here. The value in the gas token `APT` is `0.00099900 APT`. 5. Overall, you need both the events and the changes to determine the amount transferred of the account. The final balances will show in the changes alone. If you watch all of these events, you will be able to handle all possible transactions. Below is the full example of the transaction response. ### Fungible Asset Balance Changes [](#fungible-asset-balance-changes) For fungible assets, the balance changes are tracked in the `primary_fungible_store`. The primary fungible store address is deterministic, and will always be tracked by the owner of the store. An example: [https://api.mainnet.aptoslabs.com/v1/transactions/by\\\_version/1750174030](https://api.mainnet.aptoslabs.com/v1/transactions/by%5C_version/1750174030) There are a few steps when tracking fungible assets: 1. There will be two types of events for fungible assets. `0x1::fungible_asset::Deposit` and `0x1::fungible_asset::Withdraw`. `Withdraw` events are similar to the coin events, where the balance will decrease by the amount in the `data.amount` field. And similarly `Deposit` events will increase the balance by the amount in the `data.amount` field. Note that, I’ve omitted the sequence number, and GUID fields, as they do not apply to module events. Each event has a `store` field, which in this case is `0x8a9d57692a9d4deb1680eaf107b83c152436e10f7bb521143fa403fa95ef76a`. This is the address of the `FungibleStore` for the asset, where the balance is stored. Note this, for the next step. 2. Next, we take a look at the `0x1::fungible_asset::FungibleStore` changes. This will show the end state of the balance for the fungible asset. The balance is in the `data.balance` field. The `address` field will match the `store` field from the events. The identifier of the fungible asset, is the `metadata` field. It is the address of the `metadata` for the fungible asset. Additionally, to figure out the actual owner of the assets, you will need to look at the owner of the store. In this case, you will need the `0x1::object::ObjectCore`, where the `address` field matches the `store` field from the events. The `owner` field will show the asset owner’s address. similar to the coin events, if the `ObjectCore` is not found in the `changes`, it means it got deleted, and a `FungibleStoreDeletion` event must be present instead. Then you can match the `store` fields between the `Withdraw`/`Deposit` events and the `FungibleStoreDeletion` event. ### Coins migrated to Fungible Asset Balance Changes [](#coins-migrated-to-fungible-asset-balance-changes) For coins migrated to fungible assets, it is just simply tracking of the two above. A coin migrated to a fungible asset will have both the coin store changes and the primary fungible asset store changes. The amounts would need to be aggregated together, and otherwise, handled as a coin. The Fungible asset metadata address is the hash of the coin type and 0xA ``` address = sha3_256(0xA | coin_type | 0xFE) ``` Here is an example of a migrated coin with APT: [https://api.mainnet.aptoslabs.com/v1/transactions/by\\\_version/1642580695](https://api.mainnet.aptoslabs.com/v1/transactions/by%5C_version/1642580695) ## Transferring Assets [](#transferring-assets) ### Coin (or migrated coin) Transfers [](#coin-or-migrated-coin-transfers) We suggest you use `0x1::aptos_account::transfer_coins(receiver address, amount)` for transferring coins. It will register the coin if it hasn’t been registered yet, and create the associated account if it hasn’t been created yet. This will continue to work with any coins that were migrated to a fungible asset, including APT. Coins can be transferred in the following ways: * [`0x1::aptos_account::transfer_coins(receiver address, amount)`](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-framework/sources/aptos_account.move#L108-L112) - Transfer a coin to another account. * [`0x1::aptos_account::batch_transfer_coins(receiver addresses, amounts)`](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-framework/sources/aptos_account.move#L93-L106) - Transfer a coin to multiple accounts. * [`0x1::aptos_account::transfer(receiver address, amount)`](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-framework/sources/aptos_account.move#L74-L91) - Transfer specifically APT to another account. ### Fungible Asset Transfers [](#fungible-asset-transfers) We suggest you use `0x1::primary_fungible_store::transfer<0x1::object::ObjectCore>(receiver address, amount)` for transferring fungible assets. It will send the associated fungible asset, and create a primary store for the asset if it hasn’t been created yet. Caution Note: This will not create an account for the user if it hasn’t been created yet. You will need to call `0x1::aptos_account::create_account(account address)` to create the account before the user can submit transactions. ## Testing [](#testing) In order to check that everything is working correctly, we’ve provided these checks. ### Balance Checks [](#balance-checks) To test balance checks, you can check the balance for the account `0x5` for the asset `0x1::aptos_coin::AptosCoin`. The balance should show `0.002 APT`, where 0.001 APT is a coin, and 0.001 APT is a migrated coin (fungible asset). If your balance is not correct, see [Coin and Migrated Coin Balances](#coin-and-migrated-coins-balances) for more information. ### Balance Change / Transfer Checks [](#balance-change--transfer-checks) #### Check Coin Transfer [](#check-coin-transfer) To test a transfer, create a transaction to transfer 0.001 APT to another account. The transaction should be successful, and the balance should be updated, where the balance is 0.001 APT smaller and minus the gas cost associated. #### Check Fungible Asset Transfer [](#check-fungible-asset-transfer) To test a transfer, you can fund an account with the fungible asset here [https://test-token-faucet.vercel.app/](https://test-token-faucet.vercel.app/) and then transfer the fungible asset to another account. The balance should be updated according to the change, and you should be able to track the mint on the website. ## Stablecoin Addresses [](#stablecoin-addresses)
Token NameToken SymbolToken AddressSource of Address
Tether USDUSDt0x357b0b74bc833e95a115ad22604854d6b0fca151cecd94111770e5d6ffc9dc2bAptos Foundation
USDCUSDC0xbae207659db88bea0cbead6da0ed00aac12edcdda169e591cd41c94180b46f3bCircle
Ondo US Dollar YieldUSDY0xcfea864b32833f157f042618bd845145256b1bf4c0da34a7013b76e42daa53cc::usdy::USDYOndo Finance
## FAQ [](#faq) ### What is the finality of a transaction? [](#what-is-the-finality-of-a-transaction) Aptos uses a BFT consensus algorithm, so transactions are finalized immediately after committing to the blockchain. ### What is the transaction fee on a transaction? [](#what-is-the-transaction-fee-on-a-transaction) Transaction fees are variable, but for most cases here are fixed. Check out [simulating transactions](/network/blockchain/gas-txn-fee#estimating-gas-consumption-via-simulation) to get an idea of the fee. # Indexer API Access > Access Aptos Indexer GraphQL API for historical data, transactions, fungible assets, and tokens with SDK integration and direct endpoints Aptos Labs hosts a public version of the Indexer GraphQL API that anyone can use to get basic historical and aggregate data about transactions, fungible assets, and tokens from on-chain. You can explore it by hand by viewing the Hasura Explorer below for the network you are interested in. You can also access the API via the GraphQL endpoints below. For more information on the format of data in each field / table, please see the [table reference page](/build/indexer/indexer-api/indexer-reference). ## SDK Access (Primary Method) [](#sdk-access-primary-method) The primary way to use the Indexer is to access it through the [TypeScript SDK](/build/sdks/ts-sdk/fetch-data-via-sdk). The TypeScript SDK will automatically handle rate limits, and can seamlessly allow for both [Fullnode REST API](/build/apis/fullnode-rest-api) access and Indexer access depending on what data is needed. ## Hasura Explorer (Manual Queries) [](#hasura-explorer-manual-queries) Choose a network to explore the free Aptos-Hosted Indexer API using the Hasura Explorer: [Mainnet](https://cloud.hasura.io/public/graphiql?endpoint=https://api.mainnet.aptoslabs.com/v1/graphql) Hasura GraphQL Explorer for Aptos Mainnet [Testnet](https://cloud.hasura.io/public/graphiql?endpoint=https://api.testnet.aptoslabs.com/v1/graphql) Hasura GraphQL Explorer for Aptos Testnet [Devnet](https://cloud.hasura.io/public/graphiql?endpoint=https://api.devnet.aptoslabs.com/v1/graphql) Hasura GraphQL Explorer for Aptos Devnet ## GraphQL API Endpoints (Direct Access) [](#graphql-api-endpoints-direct-access) If you need to directly make GraphQL queries to the Aptos-Labs hosted Indexer API, then use the following endpoints: * **Mainnet:** `https://api.mainnet.aptoslabs.com/v1/graphql` * **Testnet:** `https://api.testnet.aptoslabs.com/v1/graphql` * **Devnet:** `https://api.devnet.aptoslabs.com/v1/graphql` ### Rate limits [](#rate-limits) Learn more about the rate limits that apply to the Aptos Labs hosted indexer API by reading the [Geomi docs](https://geomi.dev/docs/admin/billing). If you need a higher rate limit, consider the following solutions: 1. Get an API Key from [Geomi](https://geomi.dev/). Learn more about API keys at the [Geomi docs site](https://geomi.dev/docs/api-keys). 2. Run the Aptos Indexer API yourself. See the guide to self-hosting [here](/build/indexer/txn-stream/self-hosted). # Indexer API Reference > Complete GraphQL API reference for Aptos Indexer with table schemas, query examples, and field documentation for tokens and accounts The Indexer API allows you to access rich data about tokens, fungible assets, and accounts on-chain using GraphQL queries. **You can access it [here](/build/indexer/indexer-api).** For common queries, check out the sidebar for examples to work from. When building your own, this reference guide should help you determine which tables are most relevant, and how to format your queries. Caution Before relying on a table for production services, check the bottom of this page to see if that table is deprecated. If so, use the note section for guidance on what to do to migrate to a non-deprecated table. # Indexer Table Reference [](#indexer-table-reference) ## Filtering (with `where` clauses) [](#filtering-with-where-clauses) To ensure your queries filter data efficiently, check out the available indexes for each table. Some indexes are composite B-tree indexes, meaning they consist of multiple columns. B-tree indexes are ordered and perform optimally when queries utilize a left-most prefix of the indexed columns. ## General [](#general) ### `user_transactions` [](#user_transactions) Transactions filtered to user\_transactions (not system).
Index NameIndexed Columns
user_transactions_pkeyversion
user_transactions_sender_sequence_number_keysender, sequence_number
ut_epoch_indexepoch
ut_insat_indexinserted_at
ut_sender_seq_indexsender, sequence_number
user_transactions_contract_info_indexentry_function_contract_address, entry_function_module_name, entry_function_function_name
### `block_metadata_transactions` [](#block_metadata_transactions) A type of system transaction emitted once per block, useful for mapping to timestamp or epoch.
Index NameIndexed Columns
block_metadata_transactions_block_height_keyblock_height
block_metadata_transactions_pkeyversion
bmt_insat_indexinserted_at
### `account_transactions` [](#account_transactions) _Has an aggregate view for summary data called `account_transactions_aggregate`_
Index NameIndexed Columns
account_transactions_pkeyaccount_address, transaction_version
at_insat_indexinserted_at
at_version_indextransaction_version DESC
This table maps accounts and transactions that interact with that account.
FieldTypePrimary KeyDescription
delegated_staking_activitiesJoinUse the Hasura explorer to see these sub-fields.
fungible_asset_activitiesJoinReferences fungible_asset_activities.
token_activitiesJoinUse the Hasura explorer to see these sub-fields.
token_activities_aggregateJoinUse the Hasura explorer to see these sub-fields.
token_activities_v2JoinReferences token_activities_v2.
token_activities_v2_aggregateJoinReferences token_activities_v2.
account_addressString!YesThis is an Aptos account address. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
transaction_versionbigint!YesBlockchain version of the transaction. Ex. 10000000
### `ledger_infos` [](#ledger_infos) This table shares what chain is currently being queried.
FieldTypePrimary KeyDescription
chain_idintYesThe unique identifier for the chain you are accessing. Ex. 1 (for Mainnet), 2 (for Testnet), etc.
### `processor_status` [](#processor_status) This table shares how current this processor’s data is. gives you latest version processed per “processor”
FieldTypePrimary KeyDescription
last_success_versionbigintYesThe version number of the last successful processor run. Ex. 5000000
last_transaction_timestampStringTimestamp of the last processed transaction. Ex. “2024-04-17T02:14:25.68771”
last_updatedStringTimestamp of the last update to this processor’s status. Ex. “2024-04-17T02:14:25.68771”
processorStringYesName of the processor. Ex. “transaction_processor”
## NFT [](#nft) ### `token_activities_v2` [](#token_activities_v2) _Has an aggregate view for summary data called `token_activities_v2_aggregate`_
Index NameIndexed Columns
ta2_from_type_indexfrom_address, type
ta2_insat_indexinserted_at
ta2_owner_type_indexevent_account_address, type
ta2_tid_indextoken_data_id
ta2_to_type_indexto_address, type
token_activities_v2_pkeytransaction_version, event_index
This table tracks token activities and is especially useful for tracking NFT activity. This includes both v1 and v2 data.
FieldTypePrimary KeyDescription
aptos_names_fromJoinUse the Hasura explorer to see these sub-fields.
aptos_names_from_aggregateJoinUse the Hasura explorer to see these sub-fields.
aptos_names_toJoinUse the Hasura explorer to see these sub-fields.
aptos_names_to_aggregateJoinUse the Hasura explorer to see these sub-fields.
current_token_dataJoinUse the Hasura explorer to see these sub-fields.
after_valueStringThe value of a token property after the transaction. Ex. “100”
before_valueStringThe value of a token property before the transaction. Ex. “50”
entry_function_id_strStringThe identifier of the function called in this transaction. Ex. “0x1::aptos_account::transfer”
event_account_addressStringThis is an Aptos account address related to the event. This address must be 66 characters long, and so may be 0 padded. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
event_indexbigintYesIndex of the event within the transaction. Ex. 1
from_addressStringThis is an Aptos account address from which the token was sent. This address must be 66 characters long, and so may be 0 padded. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
is_fungible_v2BooleanIndicates whether the token is fungible. Soon to be deprecated. Ex. False for NFTs.
property_version_v1bigintThe version of the token’s properties under schema version 1. This field is only for token standard v1. It is always 0 for v2. Ex. 0
to_addressStringThis is an Aptos account address to which the token was sent. This address must be 66 characters long, and so may be 0 padded. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
token_amountbigintThe amount of the token transferred in this activity. Ex. 3
token_data_idStringUnique identifier for this particular token’s data. For token standard v1, this is derived from a combination of creator_address, collection_name, and token_name. This ID must be 66 characters long, and so may be 0 padded. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
token_standardStringAptos standard that the collection adheres to. Ex. “v1”
transaction_timestampStringTimestamp when the transaction occurred. Ex. “2024-04-17T02:14:25.68771”
transaction_versionbigintYesBlockchain version of the transaction. Ex. 10000000
typeStringType of transfer - like “deposit” or “withdrawal”. Ex. “0x3::token::DepositEvent”
### `nft_metadata_crawler_parsed_asset_uris` [](#nft_metadata_crawler_parsed_asset_uris) This table allows you to look up the cdn and uris for NFT images / content.
FieldTypePrimary KeyDescription
animation_optimizer_retry_countIntNumber of retries to optimize animation. Ex. 3
asset_uriStringYesURI of the asset. Ex. “https://example.com/nft/123
cdn_animation_uriStringContent Delivery Network URI for animation. Ex. “https://cdn.example.com/animations/123
cdn_image_uriStringContent Delivery Network URI for image. Ex. “https://cdn.example.com/images/123
cdn_json_uriStringContent Delivery Network URI for JSON metadata. Ex. “https://cdn.example.com/metadata/123.json
raw_animation_uriStringOriginal URI for animation before CDN optimization. Ex. “https://example.com/raw/animations/123
raw_image_uriStringOriginal URI for image before CDN optimization. Ex. “https://example.com/raw/images/123
Index NameIndexed Columns
nft_inserted_atinserted_at
nft_raw_animation_uriraw_animation_uri
nft_raw_image_uriraw_image_uri
parsed_asset_uris_pkeyasset_uri
### `current_token_ownerships_v2` [](#current_token_ownerships_v2) _Has an aggregate view for summary data called `current_token_ownerships_v2_aggregate`_ This table tracks who owns which NFTs. This includes both v1 and v2 tokens. Fungible tokens are not tracked as consistently.
FieldTypePrimary KeyDescription
composed_nfts_aggregateJoinAggregate information about the composed NFTs, such as count or other statistics.
current_token_dataJoinDetailed information about the token’s current data; structure is defined in a related table.
amountbigintThe amount of the token owned. Example: 1 for an NFT.
composed_nftsArrayAn array containing the IDs of NFTs that compose this token, if applicable.
is_fungible_v2BooleanIndicates whether the token is fungible. Example: true or null
is_soulbound_v2BooleanIndicates whether the token is soulbound (non-transferable once owned). Example: true or null
last_transaction_timestampStringTimestamp of the last transaction involving the token. Example: “2024-04-17T02:14:25.68771”
last_transaction_versionbigintThe version number of the last transaction involving the token. Example: 20747031
non_transferrable_by_ownerBooleanIndicates whether the token is non-transferrable by the owner. Example: true or null
owner_addressStringYesThe Aptos account address that currently owns the token. Addresses must be 66 characters so may be 0 padded. Example: “0xa815a9a09105973084bfc31530e7c8f002846787c2f0521e1e34dc144ad83b89”
property_version_v1bigintYesThe version number of the token’s properties as of the last update. This field is only for token standard v1. It is always 0 for v2. Example: 0
storage_idStringYesA unique identifier used for storage purposes. IDs must be 66 characters long, so may be 0 padded. Ex. “0xd8d41ff9f67d17d7dee061b5b683b92013b420cb6a30c21fc7c287454792d7a8”
table_type_v1StringThe Move function type. Example: “0x3::token::TokenStore”
token_data_idStringYesA unique identifier for the token data, typically a hash or a numeric ID. Ex. “0x3d911af2dc3e47848fbba17b8694cf526942be183b84f8393a6c048232fb976d”
token_properties_mutated_v1ObjectProperties of the token that have been mutated from the original. Often in JSON or similar format. Example:
token_standardStringThe standard used to generate this token. Ex. “v1” or “v2”
Index NameIndexed Columns
curr_to2_insat_indexinserted_at
curr_to2_owner_indexowner_address
curr_to2_wa_indexstorage_id
current_token_ownerships_v2_pkeytoken_data_id, property_version_v1, owner_address, storage_id
### `current_token_datas_v2` [](#current_token_datas_v2) This table tracks the metadata associated with each NFT (Ex. URI, supply, etc.). This tracks both v1 and v2 tokens.
FieldTypePrimary KeyDescription
cdn_asset_urisJoinUse the Hasura explorer to see these sub-fields.
current_collectionJoinUse the Hasura explorer to see these sub-fields.
current_token_ownershipsJoinUse the Hasura explorer to see these sub-fields.
current_token_ownerships_aggregateJoinUse the Hasura explorer to see these sub-fields.
aptos_nameStringThis is a name tied to this token using the Aptos Name Service (ANS). Ex. “EpicDragon”
collection_idStringYesIdentifier for the collection that includes this token. Ex. “0x360f6eeabb4d7a9d2fab1f35b01e02831e3b5c4b73c7fd6c98dcc1c301c817c8”
decimalsbigintNumber of decimal places for token value, typically for fungible tokens. Ex. 18
descriptionStringDescription of the token. Ex. “A legendary dragon from the mystical lands.”
is_fungible_v2BooleanWhether the token is fungible. Ex. False for NFTs
largest_property_version_v1bigintThe largest version number of the token’s properties under the first schema. Ex. 1
last_transaction_timestampbigintUnix timestamp of the last transaction involving this token. Ex. 2024-03-27T07:41:58.800893
last_transaction_versionbigintBlockchain version of the last transaction involving this token. Ex. 30000000
maximumbigintMaximum possible quantity of this token, relevant for fungibles. Ex. 1000000
supplybigintCurrent supply of the token in circulation. Ex. 500000
token_data_idStringUnique identifier for the token’s data. Ex. “0xa815a9a09105973084bfc31530e7c8f002846787c2f0521e1e34dc144ad83b89”
token_nameStringThe formal name of the token. Ex. “Mystic Dragon”
token_propertiesObjectUse the Hasura explorer to see these sub-fields.
token_standardStringAptos standard that the collection adheres to. Ex. “v1”
token_uriStringURI linking to further information about the token. Ex. “https://example.com/tokens/987654321
Index NameIndexed Columns
cur_td2_cid_name_indexcollection_id, token_name
cur_td2_insat_indexinserted_at
current_token_datas_v2_pkeytoken_data_id
### `current_collections_v2` [](#current_collections_v2) This table tracks the metadata associated with each NFT collection (Ex. collection\_id, creator\_address, etc.). This tracks both v1 and v2 tokens.
FieldTypePrimary KeyDescription
cdn_asset_urisJoinUse the Hasura explorer to see these sub-fields.
collection_idStringYesUnique identifier for the collection. IDs must be 66 characters long, and so may be 0 padded. Ex. “0xa815a9a09105973084bfc31530e7c8f002846787c2f0521e1e34dc144ad83b88”
collection_nameStringThe formal name of the collection. Ex. “Mythic Dragons”
creator_addressStringThis is an Aptos account address that created the collection. Addresses must be 66 characters long, and so may be 0 padded. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
current_supplybigintCurrent supply of tokens in this collection. Ex. 500
descriptionStringDescription of the collection. Ex. “A collection of rare digital dragons.”
last_transaction_timestampStringTimestamp of the last transaction involving this collection. Ex. “2024-04-17T02:14:25.68771”
last_transaction_versionbigintBlockchain version of the last transaction involving this collection. Ex. 3000000002
max_supplybigintMaximum possible quantity of tokens in this collection. If the max supply is 0, there is no limit on the supply. Ex. 1000
mutable_descriptionStringChangeable description of the collection. Ex. “Updated collection description.”
mutable_uriBooleanTrue if the uri is changeable by the creator. Ex. True
table_handle_v1StringLegacy identifier handle for the collection in earlier schema versions. Ex. “handle_12345”
token_standardStringAptos standard that the collection adheres to. Ex. “v1”
total_minted_v2bigintTotal number of tokens minted in this collection under schema version 2. Ex. 800
uriStringThis is a URI to where the image live. This can also be JSON data. Ex. “https://example.com/collections/9876543210
Index NameIndexed Columns
cur_col2_crea_cn_indexcreator_address, collection_name
cur_col2_insat_indexinserted_at
current_collections_v2_pkeycollection_id
### `current_collection_ownership_v2_view` [](#current_collection_ownership_v2_view) _Has an aggregate view for summary data called `current_collection_ownership_v2_view_aggregate`_ This table maps collections to who owns them and helps count how much of a collection is owned by other accounts.
FieldTypePrimary KeyDescription
current_collectionJoinUse the Hasura explorer to see these sub-fields.
collection_idStringYesUnique identifier for the collection. IDs must be 66 characters long, and so may be 0 padded. Ex. “0xa815a9a09105973084bfc31530e7c8f002846787c2f0521e1e34dc144ad83b89”
collection_nameStringThe formal name of the collection. Ex. “Mythic Dragons”
collection_uriStringURI linking to further information about the collection. Ex. “https://example.com/collections/9876543210
creator_addressStringThis is an Aptos account address that created the collection. Addresses must be 66 characters long, and so may be 0 padded. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
distinct_tokensbigintThe count of distinct tokens owned within this collection. Ex. 150
last_transaction_versionbigintThe version number of the last transaction involving this collection. Ex. 3000000002
owner_addressStringYesThis is an Aptos account address that currently owns the token. Addresses must be 66 characters long, and so may be 0 padded. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
single_token_uriStringURI linking to information about a specific token within the collection. Ex. “https://example.com/tokens/9876543210
token_standardStringAptos standard that the collection adheres to. Ex. “v1”
## Fungible Assets [](#fungible-assets) ### `fungible_asset_metadata` [](#fungible_asset_metadata) This tracks the metadata tied to each fungible asset (ex. decimals of precision). It includes v1 token data. This is a current\_ table.
FieldTypePrimary KeyDescription
asset_typeStringYesThe type of the asset, described by a Move resource. Ex. “0x1::aptos_coin::AptosCoin”
creator_addressStringThis is an Aptos account address that created the asset. Addresses must be 66 characters long, and so may be 0 padded. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
decimalsbigintNumber of decimal places for token value, typically for fungible tokens. Ex. 18
icon_uriStringURI for the icon of the asset. Ex. “https://cdn.example.com/icons/123
last_transaction_timestampStringTimestamp of the last transaction involving this asset. Ex. “2024-04-17T02:14:25.68771”
last_transaction_versionbigintBlockchain version of the last transaction involving this asset. Ex. 10000000
nameStringThe formal name of the asset. Ex. “Digital Gold”
project_uriStringURI linking to the project information associated with this asset. Ex. “https://www.example.com/project\_name/
supply_aggregator_table_handle_v1StringLegacy handle for the supply aggregator table from an earlier schema version. Ex. “handle_67890”
supply_aggregator_table_key_v1StringLegacy key for accessing the supply aggregator table in earlier schema versions. Ex. “key_12345”
symbolStringThe trading symbol of the asset. Ex. “DGOLD”
token_standardStringStandard that the asset adheres to. Ex. “v1”
Index NameIndexed Columns
fam_creator_indexcreator_address
fam_insat_indexinserted_at
fungible_asset_metadata_pkeyasset_type
### `fungible_asset_activities` [](#fungible_asset_activities) This tracks the activity of fungible assets. It includes v1 token data.
FieldTypePrimary KeyDescription
owner_aptos_namesJoinReferences owner_aptos_names.
owner_aptos_names_aggregateJoinReferences owner_aptos_names.
amountbigintThe amount of the asset involved in the activity. Ex. 1000
asset_typeStringYesThe type of the asset, described by a Move resource. For fungible assets, this will be the address of the metadata object. Ex. “0x1::aptos_coin::AptosCoin”
block_heightbigintThe blockchain id at which this activity occurred. Ex. 1500000
entry_function_id_strStringThe identifier of the function called in this transaction. Ex. “0x1::aptos_account::transfer”
event_indexbigintIndex of the event within the transaction. Ex. 1
gas_fee_payer_addressStringThis is an Aptos account address that paid the gas fee for the transaction. Addresses must be 66 characters long, and so may be 0 padded. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
is_frozenBooleanTrue if this activity is a freeze asset activity. Ex. null
is_gas_feeBooleanIndicates whether this activity involved a gas fee. Ex. True
is_transaction_successBooleanIndicates whether the transaction was successful. Ex. True
metadataObjectUse the Hasura explorer to see fields for metadata in this table.
owner_addressStringThis is an Aptos account address that owns the asset. Addresses must be 66 characters long, and so may be 0 padded. Ex. “0xa815a9a09105973084bfc31530e7c8f002846787c2f0521e1e34dc144ad83b89”
storage_idStringIdentifier for the storage used in the transaction. IDs must be 66 characters long, and so may be 0 padded. Ex. “0xa815a9a09105973084bfc31530e7c8f002846787c2f0521e1e34dc144ad83b89”
storage_refund_amountbigintAmount refunded for storage after the transaction. This is always in APT octas. Ex. 50
token_standardStringAptos standard that the collection adheres to. Ex. “v1”
transaction_timestampStringTimestamp when the transaction occurred. Ex. “2024-04-17T02:14:25.68771”
transaction_versionbigintBlockchain version of the transaction. Ex. 2
typeStringType of the transaction, described by a Move entry function. Ex. “0x1::coin::WithdrawEvent”
Index NameIndexed Columns
faa_at_indexasset_type
faa_gfpa_indexgas_fee_payer_address
faa_insat_idxinserted_at
faa_owner_type_indexowner_address, type
faa_si_indexstorage_id
fungible_asset_activities_pkeytransaction_version, event_index
### `current_fungible_asset_balances` [](#current_fungible_asset_balances) _Has an aggregate view for summary data called `current_fungible_asset_balances_aggregate`_ This tracks the asset balances of each account on-chain. It includes v1 token data.
FieldTypePrimary KeyDescription
amountbigintThe amount of the asset owned. Ex. 2000
asset_typeStringThe type of the asset, described by a Move resource. For v2 tokens this is the address of the fungible asset metadata object. For v1 it’s the fully qualified path of the move resource. Ex. “0x1::aptos_coin::AptosCoin”
is_frozenBooleanIndicates whether the account is frozen. Ex. False
is_primaryBooleanIndicates whether this is the primary balance of the owner. Ex. True
last_transaction_timestampStringTimestamp of the last transaction involving this balance. Ex. “2024-04-17T02:14:25.68771”
last_transaction_versionbigintBlockchain version of the last transaction involving this balance. Ex. 30000000
metadataObjectUse the Hasura explorer to see fields for metadata in current_fungible_asset_balances.
owner_addressStringThis is an Aptos account address that owns the asset. Addresses must be 66 characters long, and so may be 0 padded. Ex. “0xa815a9a09105973084bfc31530e7c8f002846787c2f0521e1e34dc144ad83b89”
storage_idStringYesIdentifier for the storage associated with this balance. IDs must be 66 characters long, and so may be 0 padded. Ex. “0xa815a9a09105973084bfc31530e7c8f002846787c2f0521e1e34dc144ad83b89”
token_standardStringAptos standard that the collection adheres to. Ex. “v1”
Index NameIndexed Columns
cufab_insat_indexinserted_at
cufab_owner_at_indexowner_address, asset_type
current_unified_fungible_asset_balances_pkeystorage_id
## Delegated Staking [](#delegated-staking) With [AIP-6](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-6.md) we added the ability for staking pools to be formed with delegated funds (delegation pools). Once these pools hold over 1M APT, they can become a staking pool (validator node). ### `current_delegated_staking_pool_balances` [](#current_delegated_staking_pool_balances) This table tracks the current balances of each account in a delegated staking pool.
FieldTypePrimary KeyDescription
staking_pool_addressStringYesThe address of the delegation pool.
total_coinsbigintAmount of APT in the staking pool.
total_sharesbigintThe total number of shares in the delegation pool.
operator_commission_percentagebigintThe commission percentage taken by the staking pool operator.
inactive_table_handleStringThe table handle for the inactive table.
active_table_handleStringThe table handle for the active table.
last_transaction_versionint8Transaction version (identifier) for the last transaction involving this staking pool.
inserted_atStringThe timestamp when the record was inserted.
Index NameIndexed Columns
current_delegated_staking_pool_balances_pkeystaking_pool_address
### `current_delegated_voter` [](#current_delegated_voter) This table tracks the current delegated voters of a delegation pool.
FieldTypePrimary KeyDescription
delegation_pool_addressStringYesThe address of the delegation pool.
delegator_addressStringYesThe address of the delegator.
table_handleStringThe table handle tracking this position.
voterStringThe address of the current voter in the delegation pool.
pending_voterStringThe address of the pending voter awaiting confirmation.
last_transaction_versionbigintThe transaction version (identifier) of the last transaction involving this delegation.
last_transaction_timestampTimestampThe block timestamp of the last transaction involving this delegation.
inserted_atTimestampThe timestamp when the record was inserted into the database.
Index NameIndexed Columns
current_delegated_voter_pkeydelegation_pool_address, delegator_address
cdv_da_indexdelegator_address
### `current_delegator_balances` [](#current_delegator_balances) This table tracks the current balances of each account in a delegated staking pool.
FieldTypePrimary KeyDescription
delegator_addressStringYesThe address of the delegator.
pool_addressStringThe address of the delegator pool.
pool_typeStringIf the shares are active or inactive
table_handleStringThe table handle for the pool.
sharesbigintThe number of shares in the pool.
parent_table_handleStringThe table handle for the parent table.
last_transaction_versionbigintTransaction version (identifier) for the last transaction involving this staking pool.
inserted_atTimestampThe timestamp when the record was inserted.
Index NameIndexed Columns
current_delegator_balances_pkeydelegator_address, pool_address, pool_type, table_handle
### `current_staking_pool_voter` [](#current_staking_pool_voter) This table tracks the current voters of a staking pool.
FieldTypePrimary KeyDescription
staking_pool_addressStringYesThe address of the staking pool.
voter_addressStringThe address of the voter.
operator_addressStringThe address of the operator.
last_transaction_versionbigintTransaction version (identifier) for the last transaction involving this staking pool.
inserted_atTimestampThe timestamp when the record was inserted.
Index NameIndexed Columns
current_staking_pool_voter_pkeystaking_pool_address
ctpv_va_indexvoter_address
ctpv_insat_indexinserted_at
### `delegated_staking_activities` [](#delegated_staking_activities) This table tracks delegated staking events.
FieldTypePrimary KeyDescription
transaction_versionbigintTransaction version (identifier) for activity
event_indexbigintThe index of the event. Ex. 1
delegator_addressStringThe address of the delegator.
pool_addressStringThe address of the pool.
event_typeStringDistributeRewards, AddStake, UnlikeStake, ReactiveStake, WithdrawStake
amountbigintThe amount being staked. Ex. 1000
inserted_atTimestampThe timestamp when the record was inserted.
Index NameIndexed Columns
delegated_staking_activities_pkeytransaction_version, event_index
dsa_pa_da_indexpool_address, delegator_address, transaction_version, event_index
dsa_insat_indexinserted_at
### `delegated_staking_pool_balances` [](#delegated_staking_pool_balances) This table tracks the historical balances of each account in a delegated staking pool.
FieldTypePrimary KeyDescription
transaction_versionbigintTransaction version (identifier) for activity
staking_pool_addressStringThe address of the delegation pool.
total_coinsbigintAmount of APT in the staking pool.
total_sharesbigintThe total number of shares in the delegation pool.
operator_commission_percentagebigintThe commission percentage taken by the staking pool operator.
inactive_table_handleStringThe table handle for the inactive table.
active_table_handleStringThe table handle for the active table.
inserted_atStringThe timestamp when the record was inserted.
Index NameIndexed Columns
delegated_staking_pool_balances_pkeytransaction_version, staking_pool_address
### `delegated_staking_pools` [](#delegated_staking_pools) This table tracks when a delegated pool was created.
FieldTypePrimary KeyDescription
staking_pool_addressStringThe address of the staking pool.
first_transaction_versionbigintThe version number of the first transaction involving this pool. Ex. 5000000
inserted_atTimestampThe timestamp when the record was inserted.
Index NameIndexed Columns
delegated_staking_pools_pkeystaking_pool_address
### `delegator_balances` [](#delegator_balances) This table tracks the historical balances of each account in a delegation pool.
FieldTypePrimary KeyDescription
transaction_versionbigintThe version number of the transaction. Ex. 5000000
write_set_change_indexbigintThe index of the write set change. Ex. 1
delegator_addressStringThe address of the delegator.
pool_addressStringThe address of the delegator pool.
pool_typeStringThe type of the pool. Ex. “delegated”
table_handleStringThe table handle for the pool.
sharesbigintThe number of shares in the pool.
parent_table_handleStringThe table handle for the parent table.
inserted_atTimestampThe timestamp when the record was inserted.
Index NameIndexed Columns
delegator_balances_pkeytransaction_version, write_set_change_index
## Aptos Naming Service (ANS) [](#aptos-naming-service-ans) ### `current_aptos_names` [](#current_aptos_names) _Has an aggregate view for summary data called `current_aptos_names_aggregate`_ This view of [`current_ans_lookup_v2`](#current_ans_lookup_v2) helps query by name instead of account.
FieldTypePrimary KeyDescription
domainStringThe domain associated with this Aptos name. Ex. “example.crypto”
domain_with_suffixStringThe full domain name including any suffix. Ex. “example.crypto.aptos”
expiration_timestampStringTimestamp when the domain registration expires. Ex. “2024-04-17T02:14:25.68771”
is_activeBooleanIndicates whether the domain is currently active. Ex. True
is_domain_ownerBooleanIndicates whether the registered address is the owner of the domain. Ex. False
is_primaryBooleanIndicates whether this is the primary domain for the registered address. Ex. True
last_transaction_versionbigintThe version number of the last transaction involving this domain. Ex. 5000000
owner_addressStringThis is an Aptos account address that owns the domain. Addresses must be 66 characters long, and so may be 0 padded. Ex. “0x123abc456def7890abcdef1234567890abcdef1234”
registered_addressStringThis is an Aptos account address registered to the domain. Addresses must be 66 characters long, and so may be 0 padded. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
subdomainStringAny subdomain part of the domain name. Ex. “sub.example”
token_nameStringThe name of the token associated with this domain. Ex. “ExampleToken”
token_standardStringAptos standard that the collection adheres to. Ex. “v1”
### `current_ans_lookup_v2` [](#current_ans_lookup_v2) This table maps tokens, standards, and addresses to human readable names.
FieldTypePrimary KeyDescription
domainStringYesThe domain associated with this Aptos name. Ex. “example.crypto”
expiration_timestampStringTimestamp when the domain registration expires. Ex. “2024-04-17T02:14:25.68771”
is_deletedBooleanIndicates whether the domain registration has been deleted. Ex. False
last_transaction_versionbigintThe version number of the last transaction involving this domain. Ex. 5000000
registered_addressStringThis is an Aptos account address registered to the domain. Addresses must be 66 characters long, and so may be 0 padded. Ex. “0x50bc83f01d48ab3b9c00048542332201ab9cbbea61bda5f48bf81dc506caa78a”
subdomainStringYesAny subdomain part of the domain name. Ex. “sub.example”
token_nameStringThe name of the token associated with this domain. Ex. “ExampleToken”
token_standardStringYesAptos standard that the collection adheres to. Ex. “v1”
Index NameIndexed Columns
ans_v2_et_indexexpiration_timestamp
ans_v2_insat_indexinserted_at
ans_v2_ra_indexregistered_address
ans_v2_tn_indextoken_name, token_standard
current_ans_lookup_v2_pkeydomain, subdomain, token_standard
## Deprecated Tables [](#deprecated-tables) The following tables are planned for deprecation, or are already deprecated. See the notes section for any direct replacements or notes on how to migrate if you currently depend on one of these tables. Please do not use any of the below tables for production services.
TableNotes
address_version_from_move_resourcesReplace with account_transactions
address_events_summaryTo query custom events, you should create a No-Code Indexer
address_version_from_eventsTo query custom events, you should create a No-Code Indexer
coin_activitiesReplace with fungible_asset_activities
coin_balancesReplace with current_fungible_asset_balances
coin_infosReplace with fungible_asset_metadata
coin_supplyNo replacement; non-realtime APT coin supply is available with this query
collection_datasReplace with current_collections_v2
current_ans_lookupReplace with current_ans_lookup_v2
current_coin_balancesReplace with current_fungible_asset_balances
current_collection_datasReplace with current_collections_v2
current_token_datasReplace with current_token_datas_v2
current_token_ownershipsReplace with current_token_ownerships_v2
events_viewTo query custom events, you should create a No-Code Indexer
move_resourcesReplace with account_transactions
move_resources_viewReplace with account_transactions
nft_marketplace_v2_*Replace with NFT Aggregator API
token_activitiesReplace with token_activities_v2
token_datasReplace with current_token_datas_v2
token_ownershipsReplace with current_token_ownerships_v2
tokensReplace with current_token_datas_v2
transactionsNo replacement; non-realtime data is available in BigQuery
transactions_viewNo replacement; non-realtime data is available in BigQuery
# Transaction Stream Service > Real-time transaction streaming service for Aptos blockchain data, supporting both Aptos-hosted and self-hosted deployment options The Transaction Stream Service is a service that listens to the Aptos blockchain and emits transactions as they are processed. These docs explain how this system works, how to use the Labs-Hosted instance of the service, and how to deploy it yourself. You can get API access to a transaction stream hosted by Aptos Labs [here](/build/indexer/txn-stream/aptos-hosted-txn-stream). # TypeScript SDK > Official TypeScript SDK for building applications on Aptos - the most comprehensive and up-to-date SDK [ ![Github Repo Stars](https://img.shields.io/github/stars/aptos-labs/aptos-ts-sdk) ](https://github.com/aptos-labs/aptos-ts-sdk)[ ![NPM Version](https://img.shields.io/npm/v/%40aptos-labs%2Fts-sdk) ](https://www.npmjs.com/package/@aptos-labs/ts-sdk)[ ![Node Version](https://img.shields.io/node/v/%40aptos-labs%2Fts-sdk) ](https://www.npmjs.com/package/@aptos-labs/ts-sdk)[ ![NPM bundle size](https://img.shields.io/bundlephobia/min/%40aptos-labs/ts-sdk) ](https://www.npmjs.com/package/@aptos-labs/ts-sdk)[ ![Static Badge](https://img.shields.io/badge/SDK_Reference-Docs) ](https://aptos-labs.github.io/aptos-ts-sdk/@aptos-labs/ts-sdk-latest) The TypeScript SDK allows you to connect, explore, and interact on the Aptos blockchain. You can use it to request data, send transactions, set up test environments, and more! ``` npm i @aptos-labs/ts-sdk ``` ## Examples [](#examples) [Quickstart](/build/sdks/ts-sdk/quickstart) See the quickstart to get a working demo in < 5 minutes [20+ Examples](https://github.com/aptos-labs/aptos-ts-sdk/tree/main/examples/typescript) Explore all of the TypeScript examples provided in the SDK repository [Comprehensive Tests](https://github.com/aptos-labs/aptos-ts-sdk/tree/main/tests/e2e) See end to end tests which demonstrate how to use each feature of the SDK ### Transfer APT in 10 lines or less [](#transfer-apt-in-10-lines-or-less) simple\_transfer.ts ``` /* eslint-disable no-console */ /** * This example shows how to use the Aptos client to create accounts, fund them, and transfer between them. */ import { Account, AccountAddress, Aptos, AptosConfig, Network, NetworkToNetworkName } from "@aptos-labs/ts-sdk"; // TODO: There currently isn't a way to use the APTOS_COIN in the COIN_STORE due to a regexconst APTOS_COIN = "0x1::aptos_coin::AptosCoin";const COIN_STORE = "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>";const ALICE_INITIAL_BALANCE = 100_000_000;const BOB_INITIAL_BALANCE = 100;const TRANSFER_AMOUNT = 100; // Default to devnet, but allow for overridingconst APTOS_NETWORK: Network = NetworkToNetworkName[process.env.APTOS_NETWORK ?? Network.DEVNET]; /** * Prints the balance of an account * @param aptos * @param name * @param address * @returns {Promise<*>} * */const balance = async (aptos: Aptos, name: string, address: AccountAddress) => { type Coin = { coin: { value: string } }; const resource = await aptos.getAccountResource({ accountAddress: address, resourceType: COIN_STORE, }); const amount = Number(resource.coin.value); console.log(`${name}'s balance is: ${amount}`); return amount;}; const example = async () => { console.log("This example will create two accounts (Alice and Bob), fund them, and transfer between them."); // Setup the client const config = new AptosConfig({ network: APTOS_NETWORK }); const aptos = new Aptos(config); // Create two accounts const alice = Account.generate(); const bob = Account.generate(); console.log("=== Addresses ===\n"); console.log(`Alice's address is: ${alice.accountAddress}`); console.log(`Bob's address is: ${bob.accountAddress}`); // Fund the accounts console.log("\n=== Funding accounts ===\n"); const aliceFundTxn = await aptos.faucet.fundAccount({ accountAddress: alice.accountAddress, amount: ALICE_INITIAL_BALANCE, }); console.log("Alice's fund transaction: ", aliceFundTxn); const bobFundTxn = await aptos.faucet.fundAccount({ accountAddress: bob.accountAddress, amount: BOB_INITIAL_BALANCE, }); console.log("Bob's fund transaction: ", bobFundTxn); // Show the balances console.log("\n=== Balances ===\n"); const aliceBalance = await balance(aptos, "Alice", alice.accountAddress); const bobBalance = await balance(aptos, "Bob", bob.accountAddress); if (aliceBalance !== ALICE_INITIAL_BALANCE) throw new Error("Alice's balance is incorrect"); if (bobBalance !== BOB_INITIAL_BALANCE) throw new Error("Bob's balance is incorrect"); // Transfer between users const txn = await aptos.transaction.build.simple({ sender: alice.accountAddress, data: { function: "0x1::coin::transfer", typeArguments: [APTOS_COIN], functionArguments: [bob.accountAddress, TRANSFER_AMOUNT], }, }); console.log("\n=== Transfer transaction ===\n"); const committedTxn = await aptos.signAndSubmitTransaction({ signer: alice, transaction: txn }); await aptos.waitForTransaction({ transactionHash: committedTxn.hash }); console.log(`Committed transaction: ${committedTxn.hash}`); console.log("\n=== Balances after transfer ===\n"); const newAliceBalance = await balance(aptos, "Alice", alice.accountAddress); const newBobBalance = await balance(aptos, "Bob", bob.accountAddress); // Bob should have the transfer amount if (newBobBalance !== TRANSFER_AMOUNT + BOB_INITIAL_BALANCE) throw new Error("Bob's balance after transfer is incorrect"); // Alice should have the remainder minus gas if (newAliceBalance >= ALICE_INITIAL_BALANCE - TRANSFER_AMOUNT) throw new Error("Alice's balance after transfer is incorrect");}; example(); ``` # Sponsored Transactions > Allow applications to pay transaction fees for users, simplifying onboarding by removing the need for gas tokens. As outlined in [AIP-39](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-39.md), sponsored transactions allow one account to pay the fees associated with executing a transaction for another account, essentially setting up a fee payer. Sponsored transactions simplify the process for onboarding users into applications by allowing the application to cover all associated fees for interacting with the Aptos blockchain. Here are two examples: * [MerkleTrade](https://merkle.trade/) offers low cost trading to those with Ethereum wallets by creating an Aptos wallet for users and covering all transaction fees so that the user does not need to acquire utility tokens for Aptos. * Community engagement applications like [Graffio](https://medium.com/aptoslabs/graffio-web3s-overnight-sensation-81a6cf18b626) offered to cover transaction fees for custodial accounts to support the collaborative drawing application for those without wallets. ## Process Overview [](#process-overview) The process for sending a sponsored transaction follows: * The sender of the transaction determines upon an operation, as defined by a `RawTransaction`. * The sender generates a `RawTransactionWithData::MultiAgentWithFeePayer` structure * Prior to the framework 1.8 release, this must contain the fee payer’s address. * After framework release 1.8, this can optionally be set to `0x0`. * (Optionally) the sender aggregates signatures from other signers. * The sender can forward the signed transaction to the fee payer to sign and forward it to the blockchain. * Upon execution of the transaction, the sequence number of the sender account is incremented, all gas fees are deducted from the gas fee payer, and all refunds are sent to the gas fee payer. Alternatively, if the fee payer knows the operation and all signers involved, the fee payer could generate and sign the transaction and send it back to the other signers to sign. ## Technical Details [](#technical-details) In Aptos, a sponsored transaction reuses the same SignedTransaction as any other user transaction: ``` pub struct SignedTransaction { /// The raw transaction raw_txn: RawTransaction, /// Public key and signature to authenticate authenticator: TransactionAuthenticator,} ``` The difference is in the `TransactionAuthenticator`, which stores the authorization from the fee payer of the transaction to extract utility fees from their account: ``` pub enum TransactionAuthenticator {... /// Optional Multi-agent transaction with a fee payer. FeePayer { sender: AccountAuthenticator, secondary_signer_addresses: Vec, secondary_signers: Vec, fee_payer_address: AccountAddress, fee_payer_signer: AccountAuthenticator, },...} ``` To prepare a sponsored transaction for an account, the account must first exist on-chain. This is a requirement that is being removed with the 1.8 framework release. As of the 1.8 framework release, an account does not need to exist on-chain. However, the first transaction for an account requires enough gas to not only execute the transaction and cover the costs associated with account creation, even if an account already exists. Future improvements to the account model intend to eliminate this requirement. During signing of the transaction, all parties sign the following: ``` pub enum RawTransactionWithData {... MultiAgentWithFeePayer { raw_txn: RawTransaction, secondary_signer_addresses: Vec, fee_payer_address: AccountAddress, },} ``` Prior to framework release 1.8, all signers were required to know the actual fee payer address prior to signing. As of framework release 1.8, signers can optionally set the address to `0x0` and only the fee payer must sign with their address set. ## SDK Support [](#sdk-support) These are demonstrations of sponsored transactions: * The TypeScript SDK has [several examples](https://github.com/aptos-labs/aptos-ts-sdk/tree/main/examples/typescript-esm/sponsored_transactions) * The Python SDK has an example in [fee\_payer\_transfer\_coin.py](https://github.com/aptos-labs/aptos-python-sdk/blob/main/examples/fee_payer_transfer_coin.py). * The Rust SDK has a test case in [the API tests](https://github.com/aptos-labs/aptos-core/blob/0a62e54e13bc5da604ceaf39efed5c012a292078/api/src/tests/transactions_test.rs#L255). # Orderless Transactions > Execute transactions out of order for multi-machine signing scenarios while maintaining replay protection and security. As outlined in [AIP-123](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-123.md), orderless transactions allow for transactions to be executed out of order, which is particularly useful in scenarios where multiple machines need to sign for a single sending account, but the order in which they sign does not affect the outcome of the transaction or matter to the creator. Replay is protected by a nonce, which is a unique identifier for a transaction. This allows for the transaction to be executed at any time within the expiration time, regardless of the order in which the machines sign the transaction, but not be able to be replayed after the nonce has expired. The maximum expiration time is 60 seconds for orderless transactions, which is not the same for sequence number transactions. ## Process Overview [](#process-overview) Orderless transactions are dependent on the transaction payload specified in [AIP-129](https://github.com/aptos-foundation/AIPs/blob/main/aips/aip-129.md). The process for building and executing an orderless transaction is as follows: 1. Build a transaction with a `replayProtectionNonce` and a `TransactionPayload::TransactionPayloadPayload` that defines the operation to be executed. 2. Sign and submit the transaction as any other transaction, but with the `replayProtectionNonce` set. Ideally, the nonce should be a random u64 value. Note, that the behavior of the `replayProtectionNonce` is similar to a sequence number, but it does not guarantee ordered execution of transactions. Instead, it ensures that the transaction is unique and cannot be replayed (executed twice) with the same nonce. ## SDK Support [](#sdk-support) These are demonstrations of sponsored transactions: * The [TypeScript SDK](/build/sdks/ts-sdk/building-transactions/orderless-transactions) has documentation * The [Go SDK](https://github.com/aptos-labs/aptos-go-sdk/tree/main/examples/orderless_transaction) has an example # Aptos Keyless > Integrate Keyless accounts for seamless user onboarding using social logins instead of traditional private key management. ## Integrate with Aptos Keyless accounts [](#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 [](#using-an-iam-provider-integrate-with-aptos-federated-keyless) * [Federated Keyless](/build/guides/aptos-keyless/federated-keyless) # Transaction Management > Build scalable transaction management systems on Aptos with proper account handling and sequence number management. This guide explains how to build a transaction management harness that can scale on the Aptos blockchain. ## Background [](#background) In Aptos, transactions are mapped back to an account in terms of the entity that signs or authorizes that transaction and provides an account-based sequence number. When the Aptos network receives a new transaction, several rules are followed with respect to this: * The transaction sent from an account must be authorized correctly by that account. * The current time as defined by the most recent ledger update must be before the expiration timestamp of the transaction. * The transaction’s sequence number must be equal to or greater than the sequence number on-chain for that account. Once the initial node has accepted a transaction, the transaction makes its way through the system by an additional rule. If a transactions sequence number is higher than the current on-chain sequence number, it can only progress toward consensus if every node in the path has seen a transaction with the sequence number between the on-chain state and the current sequence number. Example: Alice owns an account whose current on-chain sequence number is 5. Alice submits a transaction to node Bob with sequence number 6. Bob the node accepts the transaction but does not forward it, because Bob has not seen 5. In order to make progress, Alice must either send Bob transaction number 5 or Bob must be notified from consensus that 5 was committed. In the latter, Alice submitted the transaction through another node. Beyond this there are two remaining principles: * A single account can have at most 100 uncommitted transactions submitted to the blockchain. Any more than that and the transactions will be rejected. This can happen silently if Alice submits the first 100 to Bob the node and the next 100 to Carol the node. If both those nodes share a common upstream, then that upstream will accept Alice’s 100 sent via Bob but silently reject Alice’s 100 sent via Carol. * Submitting to distinct transactions to multiple nodes will result in slow resolution as transactions will not make progress from the submitted node until the submitted knows that all preceding transactions have been committed. For example, if Alice sends the first 50 via Bob and the next 50 via Carol. ## Building a Transaction Manager [](#building-a-transaction-manager) Now that we understand the nuances of transactions, let’s dig into building a robust transaction manager. This consists of the following core components: * A sequence number generator that allocates and manages available sequence numbers for a single account. * A transaction manager that receives payloads from an application or a user, sequence numbers from the sequence number generator, and has access to the account key to combine the three pieces together into a viable signed transaction. It then also takes the responsibility for pushing the transaction to the blockchain. * An on-chain worker, leader harness that lets multiple accounts share the signer of a single shared account. Currently, this framework assumes that the network builds no substantial queue, that is a transaction that is submitted executes and commits with little to no delay. In order to address high demand, this work needs to be extended with the following components: * Optimizing `base_gas_unit` price to ensure priority transactions can be committed to the blockchain. * Further handling of transaction processing rates to ensure that the expiration timer is properly set. * Handling of transaction failures to either be ignored or resubmitted based upon desired outcome. Note, an account should be managed by a single instance of the transaction manager. Otherwise, each instance of the transaction manager will likely have stale in-memory state resulting in overlapping sequence numbers. ### Implementations [](#implementations) * Python * [Sequence number manager](https://github.com/aptos-labs/aptos-core/pull/7987) * [Transaction manager](https://github.com/aptos-labs/aptos-core/pull/7987) * [Worker-leader smart contract](https://github.com/aptos-labs/aptos-core/pull/7986) ### Managing Sequence Numbers [](#managing-sequence-numbers) Each transaction requires a distinct sequence number that is sequential to previously submitted transactions. This can be provided by the following process: 1. At startup, query the blockchain for the account’s current sequence number. 2. Support up to 100 transactions in flight at the same time, that is 100 sequence numbers can be allocated without confirming that any have been committed. 3. If there are 100 transactions in flight, determine the actual committed state by querying the network. This will update the current sequence number. 4. If there are less than 100 transactions in flight, return to step 2. 5. Otherwise, sleep for .1 seconds and continue to re-evaluate the current on-chain sequence number. 6. All transactions should have an expiration time. If the expiration time has passed, assume that there has been a failure and reset the sequence number. The trivial case is to only monitor for failures when the maximum number of transactions are in flight and to let other services manages this otherwise. In parallel, monitor new transactions submitted. Once the earliest transaction expiration time has expired synchronize up to that transaction. Then repeat the process for the next transaction. If there is any failure, wait until all outstanding transactions have timed out and leave it to the application to decide how to proceed, e.g., replay failed transactions. The best method to waiting for outstanding transactions is to query the ledger timestamp and ensure it is at least elapsed the maximum timeout from the last transactions submit time. From there, validate with mempool that all transactions since the last known committed transaction are either committed or no longer exist within the mempool. This can be done by querying the REST API for transactions of a specific account, specifying the currently being evaluated sequence number and setting a limit to 1. Once these checks are complete, the local transaction number can be resynchronized. These failure handling steps are critical for the following reasons: * Mempool does not immediate evict expired transactions. * A new transaction cannot overwrite an existing transaction, even if it is expired. * Consensus, i.e., the ledger timestamp, dictates expirations, the local node will only expire after it sees a committed timestamp after the transactions expiration time and a garbage collection has happened. ### Managing Transactions [](#managing-transactions) Once a transaction has been submitted it goes through a variety of steps: 1. Submission to a REST endpoint. 2. Pre-execution validation in the Mempool during submission. 3. Transmission from Mempool to Mempool with pre-execution validation happening on each upstream node. 4. Inclusion in a consensus proposal. 5. One more pre-execution validation. 6. Execution and committing to storage. There are many potential failure cases that must be considered: * Failure during transaction submission (1 and 2): * Visibility: The application will receive an error either that the network is unavailable or that the transaction failed pre-execution validation. * If the error is related to availability or duplicate sequence numbers, wait until access is available and the sequence number has re-synchronized. * Pre-execution validation failures are currently out of scope, outside of those related to duplicate sequence numbers, account issues are likely related to an invalid key for the account or the account lacks sufficient funds for gas. * Failure between submission and execution (3, 4, and 5): * Visibility: Only known by waiting until the transaction has expired. * These are the same as other pre-execution validation errors due to changes to the account as earlier transactions execute. It is likely either duplicate sequence numbers or the account lacks sufficient funds for gas. * Failure during execution (6): * Visibility: These are committed to the blockchain. * These errors occur as a result of on-chain state issues, these tend to be application specific, such as an auction where a new bid might not actually be higher than the current bid. ### Workers and Identity [](#workers-and-identity) Using the above framework, a single account can push upwards of 100 transactions from the start of a block to the end of a block. Assuming that all 100 transactions are consumed within 1 block, it will take a bit of time for the next 100 slots to be available. This is due to the network delays as well as the multi-staged validator pipeline. To fully leverage the blockchain for massive throughput, using a single user account is not enough. Instead, Aptos supports the concept of worker accounts that can share the responsibility of pushing work through a shared account, also known as a resource account. In this model, each worker has access to the `SignerCap` of the shared account, which enables them to impersonate the shared account or generate the `signer` for the shared account. Upon gaining the `signer`, the transaction can execute the logic that is gated by the signer of the shared account. Another model, if viable, is to decouple the `signer` altogether away from permissions and to make an application specific capability. Then this capability can be given to each worker that lets them operate on the shared infrastructure. Note that parallelization on the shared infrastructure can be limited if any transaction would have any read or write conflicts. This won’t prevent multiple transactions from executing within a block, but can impact maximum blockchain performance. # AI Tools for Aptos Development > Use AI tools like Claude, Cursor, and GitHub Copilot to build on Aptos faster. Access the Aptos MCP server and LLMs.txt documentation feeds. Aptos provides first-class support for AI-powered development workflows. Whether you’re using an AI coding assistant or an AI chat tool, you can give it deep knowledge of the Aptos blockchain, Move language, SDKs, and APIs. ## AskAptos Chatbot [](#askaptos-chatbot) The AskAptos chatbot is built into the documentation site — look for it in the top-right corner of the navigation bar. It can answer questions about Aptos concepts, help you plan implementations, and point you to the right documentation pages. ## Aptos MCP Server [](#aptos-mcp-server) The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) lets AI coding tools directly call Aptos APIs, query on-chain data, and generate correct Aptos code — without needing to copy-paste documentation. [Claude Code](/build/ai/aptos-mcp/claude) Set up the Aptos MCP server for Claude Code [Cursor](/build/ai/aptos-mcp/cursor) Set up the Aptos MCP server for Cursor ## Aptos Agent Skills [](#aptos-agent-skills) [Aptos Agent Skills](https://github.com/aptos-labs/aptos-agent-skills) provides pre-built AI skills that give coding assistants deep Aptos expertise — covering Move smart contracts, the TypeScript SDK, and full-stack dApp scaffolding. ``` npx skills add aptos-labs/aptos-agent-skills ``` This command uses the [Skills CLI](https://www.npmjs.com/package/skills), which is invoked via `npx`. If `npx skills` is not available in your environment, ensure you have Node.js and npm installed and refer to the Skills CLI documentation for installation and troubleshooting details. [Aptos Agent Skills](/build/ai/aptos-agent-skills) Browse available skills for Move development, TypeScript SDK, and project scaffolding ## LLMs.txt Documentation Feeds [](#llmstxt-documentation-feeds) The [LLMs.txt standard](https://llmstxt.org/) provides machine-readable documentation feeds that AI tools can ingest to understand the full Aptos documentation. We publish three feeds to suit different context window sizes:
FeedURLBest for
llms.txt/llms.txtStructured index with page titles, descriptions, and per-page .md links
llms-small.txt/llms-small.txtCondensed docs for smaller context windows
llms-full.txt/llms-full.txtFull documentation — all pages concatenated
Some clients resolve `/.well-known/llms.txt`; production serves the same index via a redirect to [`/llms.txt`](/llms.txt) ([`https://aptos.dev/.well-known/llms.txt`](https://aptos.dev/.well-known/llms.txt)). The [`llms.txt`](/llms.txt) router also surfaces machine-readable **API** links—[`/aptos-spec.json`](/aptos-spec.json) (OpenAPI 3 JSON for the node REST API) and [`/rest-api`](/rest-api) (HTML reference)—plus **MCP**, Agent Skills, Explorer, GitHub, standards, and Indexer GraphQL `.md` links in one place. [How to use LLMs.txt with AI tools](/llms-txt) Instructions for Cursor, GitHub Copilot, Claude.ai, ChatGPT, Windsurf, and more ## Agent discovery endpoints [](#agent-discovery-endpoints) The docs site publishes a handful of standardized discovery documents so coding agents can bootstrap from a single root. Every page also returns a [`Link`](https://www.rfc-editor.org/rfc/rfc8288) response header and matching `` tags that advertise the same URLs.
EndpointPurpose
/.well-known/api-catalogRFC 9727 linkset pointing at the REST API spec, documentation, Indexer GraphQL, and the LLMs.txt feeds.
/.well-known/mcp/server-card.jsonMCP Server Card (SEP-2127) describing the @aptos-labs/aptos-mcp server.
/.well-known/agent-skills/index.jsonAgent Skills Discovery index for aptos-agent-skills with per-skill SHA-256 digests.
/.well-known/oauth-protected-resourceOAuth 2.0 Protected Resource Metadata (RFC 9728) for the Google-authenticated Aptos Testnet Faucet. Lists the resource identifier, authorization servers, and supported scopes.
/.well-known/openid-configurationOpenID Connect Discovery 1.0 document advertising the issuer, authorization/token endpoints, JWKS URI, and supported grant types used by the Aptos Testnet Faucet sign-in flow.
/.well-known/oauth-authorization-serverOAuth 2.0 Authorization Server Metadata (RFC 8414) mirror of the OIDC discovery document for clients that prefer the pure OAuth 2.0 endpoint name.
/robots.txtIncludes Content Signals (ai-train=yes, search=yes, ai-input=yes) so agents know Aptos docs are opted in.
The OAuth/OIDC discovery documents apply only to the [Aptos Testnet Faucet](/network/faucet); the rest of `aptos.dev` is unauthenticated public documentation. Agents that need to fund a testnet account can call `/.well-known/oauth-protected-resource` to discover the faucet’s resource identifier and the OIDC issuers (Firebase + Google) that mint the bearer tokens it accepts on `Authorization: Bearer …`. ### Markdown content negotiation [](#markdown-content-negotiation) Any docs URL that has a `.md` mirror (for example [`/build/sdks`](/build/sdks) → [`/build/sdks.md`](/build/sdks.md)) will also respond to `Accept: text/markdown` with `Content-Type: text/markdown`: ``` curl -H "Accept: text/markdown" https://aptos.dev/build/sdks ``` HTML stays the default for browsers that send the usual `Accept: text/html`. ### WebMCP [](#webmcp) Chrome and other browsers that implement the [WebMCP proposal](https://webmachinelearning.github.io/webmcp/) can discover the following tools on every docs page via `navigator.modelContext`: `aptos-docs.search`, `aptos-docs.open-doc`, `aptos-docs.fetch-doc-markdown`, and `aptos-docs.list-llms-feeds`. # Aptos Model Context Protocol (MCP) > Learn how to use the Aptos MCP server to build applications with AI tools like Cursor and Claude Code The [Aptos MCP server](https://github.com/aptos-labs/aptos-npm-mcp) (`npx @aptos-labs/aptos-mcp`) provides tools, prompts, and resources to help developers build applications on the Aptos blockchain through [Geomi](https://geomi.dev). It is designed to be used with AI tools like Cursor, Claude Code, and others that support the [Model Context Protocol](https://modelcontextprotocol.io/). ## Getting Started [](#getting-started) ### Prerequisites [](#prerequisites) * [node and npm](https://nodejs.org/en) * Build Bot Api Key ### Generate a 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/](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 [](#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. [Claude Code](/build/ai/aptos-mcp/claude) Set up for Claude Code [Cursor](/build/ai/aptos-mcp/cursor) Set up for Cursor # LLMs.txt > How to get tools like Cursor, GitHub Copilot, ChatGPT, and Claude to understand Aptos documentation. ## What is LLMs.txt? [](#what-is-llmstxt) We support [LLMs.txt](https://llmstxt.org/) files for making the Aptos documentation available to large language models (LLMs). This feature helps AI tools better understand the Aptos blockchain, its Move language, SDKs, and development patterns. ## Available Routes [](#available-routes) We provide the following LLMs.txt routes to help AI tools access our documentation: * [llms.txt](/llms.txt) - A compact routing file that points AI tools to the most useful Aptos docs and machine-readable exports * [llms-small.txt](/llms-small.txt) - A curated low-token subset of the most useful Aptos documentation for IDE assistants and smaller context windows * [llms-full.txt](/llms-full.txt) - The full rendered Aptos documentation corpus for large-context ingestion **Well-known URL:** Some tools look for [`https://aptos.dev/.well-known/llms.txt`](https://aptos.dev/.well-known/llms.txt). That URL permanently redirects to [`/llms.txt`](/llms.txt) (same content). The [`llms.txt`](/llms.txt) index also lists **structured API assets** that are not prose docs—for example the [Aptos Fullnode OpenAPI spec](/aptos-spec.json) (JSON) and the [REST API reference](/rest-api) (HTML) generated from that spec. It also surfaces **agent tooling** (Aptos MCP, Agent Skills, Explorer, GitHub org) and key **Markdown** deep links (AI hub, standards, Indexer GraphQL reference) so models can fetch the right surface without guessing URLs. ## Per-Page Markdown Access [](#per-page-markdown-access) Every documentation page is also available as rendered Markdown by appending `.md` to the URL:
Page URLMarkdown URL
https://aptos.dev/build/guides/first-transactionhttps://aptos.dev/build/guides/first-transaction.md
https://aptos.dev/build/sdks/ts-sdkhttps://aptos.dev/build/sdks/ts-sdk.md
https://aptos.dev/zh/build/guides/first-transactionhttps://aptos.dev/zh/build/guides/first-transaction.md
This is useful for AI tools that need to fetch individual pages with minimal tokens, rather than ingesting the full documentation. The [llms.txt](/llms.txt) file acts as a compact router, while [llms-small.txt](/llms-small.txt) and [llms-full.txt](/llms-full.txt) provide curated and comprehensive corpus exports. ## Usage with AI Tools [](#usage-with-ai-tools) ### Claude Code [](#claude-code) Add Aptos documentation context to [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/overview) projects: 1. Add `https://aptos.dev/llms.txt` to your project’s `CLAUDE.md` file as a reference 2. Claude Code will read the index and fetch relevant pages via `.md` URLs as needed 3. For deeper integration with on-chain tools, see [Aptos MCP for Claude Code](/build/ai/aptos-mcp/claude) ### Cursor [](#cursor) Use the `@Docs` feature in Cursor to include the LLMs.txt files in your project. This helps Cursor provide more accurate code suggestions and documentation for Aptos development. [Read more about @Docs in Cursor](https://docs.cursor.com/context/@-symbols/@-docs) ### GitHub Copilot [](#github-copilot) GitHub Copilot can leverage the information in these LLMs.txt files to provide better assistance when developing Aptos applications. You can reference these files in your GitHub Copilot Chat by using the following URLs: ``` https://aptos.dev/llms.txthttps://aptos.dev/llms-small.txthttps://aptos.dev/llms-full.txt ``` ### Windsurf [](#windsurf) Reference the LLMs.txt files using `@` or in your `.windsurfrules` files to enhance Windsurf’s understanding of Aptos development. [Read more about Windsurf Memories](https://docs.codeium.com/windsurf/memories#memories-and-rules) ### Claude.ai [](#claudeai) Add Aptos documentation as a knowledge source in [Claude Projects](https://claude.ai): 1. Open [Claude.ai](https://claude.ai) and create or open a Project 2. Click **Add content** 3. Paste `https://aptos.dev/llms-full.txt` as a URL source 4. Claude will now have Aptos documentation context in all conversations within that Project ### ChatGPT [](#chatgpt) Reference the Aptos docs directly in ChatGPT conversations: * Paste `https://aptos.dev/llms-full.txt` into your message and ask ChatGPT to read it before answering Aptos questions * For [custom GPTs](https://openai.com/index/introducing-gpts/): add `https://aptos.dev/llms.txt` as a knowledge source in the GPT Builder ### Other AI Tools [](#other-ai-tools) Any AI tool that supports LLMs.txt can use these routes to better understand Aptos. Simply point your tool to any of the routes above. # Aptos Network Nodes > Learn about validator nodes, validator fullnodes, and public fullnodes that power the Aptos network The Aptos network consists of three node types: validator nodes, validator fullnodes (VFNs), and public fullnodes (PFNs). To participate in consensus, you are required to run a validator node and stake the minimum amount of utility coins. VFNs and PFNs are not required to participate in consensus, but they are necessary to distribute blockchain data and enable ecosystem services, e.g., indexing, querying, and RESTful API services (see [Aptos APIs](/build/apis)). VFNs can only be run by validator operators, while PFNs can be run by anyone. You can learn more about the different types of nodes in the [Blockchain Deep Dive](/network/blockchain) section. This section provides detailed, step-by-step instructions on how to deploy and operate Aptos nodes in different environments. It also describes everything you need to stake and participate in consensus and governance. ## Quick Links [](#quick-links) ### Validation on Aptos [](#validation-on-aptos) Everything you need to know about how validation, staking and governance works on Aptos. [How validation works](/network/blockchain/staking#validation-on-the-aptos-blockchain) Validator-leader proposes and earns rewards on success. [Validator states](/network/blockchain/staking#validator-state-and-stake-state) Learn how a validator gets into a validator set. ### Staking [](#staking) [Staking on Aptos](/network/blockchain/staking) A comprehensive guide to how staking works on Aptos. [Governance](/network/blockchain/governance) Who can propose, who can vote, and how an AIP is resolved. [Owner](/network/nodes/validator-node/connect-nodes/staking-pool-operations) Describes the owner operations performed for staking. [Voter](/network/nodes/validator-node/connect-nodes/staking-pool-voter) Describes the voter operations performed for staking. ### Validators and VFNs [](#validators-and-vfns) A comprehensive guide to deploying nodes, staking operations and participate in consensus. [Node requirements](/network/nodes/validator-node/node-requirements) Details the compute and storage resources you need. Read this first before anything. [Running validator node](/network/nodes/validator-node/deploy-nodes) In the cloud or on-premises, Docker or source, you will read step-by-step instructions here. [Node health](/network/nodes/validator-node/verify-nodes/node-liveness-criteria) You can verify your node health using several options. [Connecting to Aptos network](/network/nodes/validator-node/connect-nodes/connect-to-aptos-network) Steps to connect your nodes to an Aptos network. [Staking pool operations](/network/nodes/validator-node/connect-nodes/staking-pool-operations) Step-by-step guide for how to perform staking pool operations. [Shutting down nodes](/network/nodes/validator-node/modify-nodes/shutting-down-nodes) Leave the validator set first, and then shut down your node. ### Public Fullnodes (PFNs) [](#public-fullnodes-pfns) A section with detailed, step-by-step instructions on everything related to Aptos PFNs. [Deploy a PFN](/network/nodes/full-node/deployments) Follow this section to deploy a PFN. [Indexer PFN](/build/indexer/legacy/indexer-fullnode) Describes how to run an indexer PFN on the Aptos network. ### Common Operations [](#common-operations) [Develop with localnet](/network/nodes/localnet/local-development-network) Run a localnet for development (including validator nodes). [Upgrade your PFN](/network/nodes/full-node/modify/update-fullnode-with-new-releases) Upgrade your node with new releases. [Bootstrap from a snapshot](/network/nodes/bootstrap-fullnode/bootstrap-fullnode) Use a snapshot to bootstrap a new node. [Bootstrap from a backup](/network/nodes/bootstrap-fullnode/aptos-db-restore) Use data restore to bootstrap a new node. # Run a Public Fullnode > Deploy and operate your own public fullnode (PFN) to synchronize with the Aptos blockchain and stay up-to-date with the latest state. You can run your own public fullnode (PFN) to synchronize the state of the Aptos blockchain and stay up-to-date. PFNs replicate the entire state of the blockchain by syncing from other Aptos VFNs and PFNs. PFNs can be run by anyone. This section explains how to deploy a PFN and connect to an Aptos network. You can learn more about the different types of nodes in the [Blockchain Deep Dive](/network/blockchain) section. # Run a Validator and VFN > Learn how to participate in the Aptos consensus protocol by deploying and running a validator node and validator fullnode (VFN) with step-by-step guidance. To participate in the Aptos consensus protocol, you must deploy and run a validator node and (optionally) a validator fullnode (VFN). This document provides a high-level overview of the important steps required for deploying both node types. Before initializing a staking pool or delegation pool, read about [Staking](/network/blockchain/staking) and [Delegated Staking](/network/blockchain/delegated-staking) to learn the differences between the stake pool types. Note that once a stake pool has been created, it cannot be changed to a delegation pool or vice versa. Use the documents within this section to run an Aptos validator and a VFN. At a high-level, the process is as follows: 1. Understand the requirements and deployment types. Read the node requirements and select a deployment method (e.g., on-premises or cloud services). Start by reading the node requirements to get to know the compute, memory, networking and storage resources you need. Also, select a method to deploy your nodes, i.e., use cloud managed Kubernetes, Docker, or source code. 2. Generate identities for your nodes. Create your public/private keypairs and account addresses for the validator and VFN. Remember to keep your private keys confidential! 3. Configure your validator and VFN. Configure your nodes to use the generated keys and identities. Using YAML files, configure your nodes with the keys and identities generated in the previous step. This is required to allow your nodes to connect to other nodes (i.e., peers) securely. 4. Download genesis and a waypoint for your nodes. Bootstrap the nodes with a genesis and waypoint, and prepare them for startup. With the nodes configured correctly, install the binaries and download the genesis blob and waypoint files. These will give your nodes the information they need to start syncing with other peers. 5. Join the validator set and start participating. Initialize the staking pool, join the validator set and start validating to earn rewards. Before other peers will accept connections from your nodes, you will need to join the validator set. To do this, you must initialize a staking pool and delegate to operators and voters. Once your staking pool has been set up, you can join the validator set. At this point your nodes will begin to sync with the network and your validator will be able to start participating in consensus. This is when you can start earning rewards. # Latest Aptos Releases > Find the latest Aptos releases for mainnet, testnet, and devnet with their corresponding GitHub branches Each Aptos release can be found on the GitHub site for [Aptos-core releases](https://github.com/aptos-labs/aptos-core/releases). Each release is mirrored by the following git branches: * [Latest Mainnet Release](https://github.com/aptos-labs/aptos-core/tree/mainnet) * [Latest Testnet Release](https://github.com/aptos-labs/aptos-core/tree/testnet) * [Latest Devnet Release](https://github.com/aptos-labs/aptos-core/tree/devnet) Aptos typically conducts multiple devnet releases for each testnet and mainnet release. Hence, devnet releases use commit hashes for tracking rather than version numbers. Testnet and mainnet releases usually have a one-to-one correlation, meaning each testnet release rolls into mainnet. Hot fixes are exceptions that may occur in mainnet to address urgent issues in production. See the [Aptos Release Process](https://github.com/aptos-labs/aptos-core/blob/main/RELEASE.md) for more details. ## Update nodes [](#update-nodes) If you are a node operator, [update your nodes with the new release](/network/nodes/full-node/modify/update-fullnode-with-new-releases). ## Subscribe to Release Announcements [](#subscribe-to-release-announcements) ### Subscribe via GitHub [](#subscribe-via-github) 1. Go to the [aptos-labs/aptos-core](https://github.com/aptos-labs/aptos-core) repository. 2. Open the **Watch** menu and select **Custom**. 3. Select the **Releases** checkbox and click **Apply**. ### Subscribe via [Aptos Discord](https://discord.gg/aptosnetwork) [](#subscribe-via-aptos-discord) Join the Aptos Discord server to interact with us and our community. We also post upcoming releases in these channels. * [#mainnet-release](https://discord.com/channels/945856774056083548/1042502400507916349) * [#testnet-release](https://discord.com/channels/945856774056083548/1025614160555413545) * [#devnet-release](https://discord.com/channels/945856774056083548/956692649430093904) ### Subscribe via [Aptos Twitter](https://x.com/AptosRelease) [](#subscribe-via-aptos-twitter) Follow [@AptosRelease](https://x.com/AptosRelease) on Twitter to get the latest updates about our upcoming mainnet releases and be notified when it is time to update your node. Every couple of days, [@AptosRelease](https://x.com/AptosRelease) will tweet a countdown to remind you to update to the latest version. _Note: We do not post about hotfixes here!_ ## Aptos Release Process [](#aptos-release-process) To understand how we conduct releases, review the [Aptos Release Process](https://github.com/aptos-labs/aptos-core/blob/main/RELEASE.md). # Aptos Glossary > Comprehensive glossary of terms and concepts used throughout the Aptos ecosystem and documentation ## A [](#a) ### Accumulator Root Hash [](#accumulator-root-hash) * An **accumulator root hash** is the root hash of a [Merkle accumulator](https://eprint.iacr.org/2009/625.pdf). ### Account [](#account) * An **account** in the Aptos blockchain is a container for an arbitrary number of [Move modules](#move-module) and [Move resources](#move-resources). * The state of each account is composed of both code and data. * The account is identified by [account address](#account-address). See [Accounts](/network/blockchain/accounts) for more information. ### Account Address [](#account-address) * An **account address** is the address of an Aptos account. * Account address refers to a specific destination on the Aptos network. The address dictates the destination and source of a specific amount of assets exchanged by two parties on the blockchain. * Aptos addresses are 64-character hex string (32 bytes). Often times these strings are prefixed with `0x` and for first 16 addresses, the leading 0s are excluded (ex. `0x1`) See [Accounts](/network/blockchain/accounts) for more information. ### API [](#api) * An **Application Programming Interface (API)** is a set of protocols and tools that allow users to interact with Aptos blockchain nodes and client networks via external applications. Aptos offers a REST API to communicate with our nodes. * See [documentation](/build/apis) for more details. ### APT [](#apt) **Aptos token (APT)** is the Aptos blockchain native token used for paying network and transaction fees. ### Aptos [](#aptos) **Aptos** is a Layer 1 blockchain for everyone. It uses the Move programming language and launched its mainnet on 2022-10-17 to redefine the web3 user experience. The Aptos blockchain is dedicated to creating better user experiences through increased speed, security, scalability, reliability and usability with low transaction costs. The word “Aptos” means “The People” in the Ohlone language. Learn more about the Aptos blockchain on the [official Aptos website](https://aptosnetwork.com). ### AptosBFT [](#aptosbft) * **AptosBFT** is the Aptos protocol’s BFT consensus algorithm. * AptosBFT is based on Jolteon. ### Aptos Blockchain [](#aptos-blockchain) * The **Aptos blockchain** is a ledger of immutable transactions agreed upon by the validators on the Aptos network (the network of validators). ### Aptos Name Service (ANS) [](#aptos-name-service-ans) * The **Aptos Name Service (ANS)** is a decentralized naming address service for the Aptos blockchain. An Aptos name is a human-readable _.apt_ domain name that is used in place of a public key, for example _love.apt_. * This service also allows users to register subdomain names in addition to the registered domain. Find out more at: [Aptosnames.com](https://www.aptosnames.com/) ### Aptos Core [](#aptos-core) **Aptos-core** is the [open-source repository](https://github.com/aptos-labs/aptos-core/) containing the code for Aptos Network software. Aptos-core contains software for * the Aptos blockchain itself, which generates and stores the immutable ledger of confirmed transactions and * the validation process, which implements the consensus algorithm to validate transactions and add them to the Aptos blockchain immutable ledger. ### Aptos Ecosystem [](#aptos-ecosystem) * **Aptos ecosystem** refers to various components of the Aptos blockchain network and their interactions. The Aptos ecosystem includes the community, [community-driven projects](https://aptosnetwork.com/ecosystem/directory), and [events](https://aptosnetwork.com/events). ### Aptos Explorer [](#aptos-explorer) * The **[Aptos Explorer](https://explorer.aptoslabs.com/)** is an interface that helps users examine details of the Aptos blockchain, including account information, validators, and transactions. * The Aptos Explorer help users validate their work in Aptos wallets and other tools in the blockchain. ### Aptos Framework [](#aptos-framework) The **Aptos Framework** defines the public API for blockchain updates and the structure of on-chain data. It defines the business logic and access control for the three key pillars of Aptos functionality: payments, treasury, and on-chain governance. It is implemented as a set of modules written in the Move programming language and stored on-chain as Move bytecode. ### Aptos Node [](#aptos-node) An **Aptos node** is a peer entity of the Aptos network that tracks the state of the Aptos blockchain. There are two types of Aptos nodes, [validators](#validator) and [fullnodes](#fullnodes). ### Aptos Protocol [](#aptos-protocol) * **Aptos protocol** is the specification of how transactions are submitted, ordered, executed, and recorded within the Aptos network. ### AptosAccount [](#aptosaccount) * A **`AptosAccount`** is a Move resource that holds all the administrative data associated with an account, such as sequence number, balance, and authentication key. * A **`AptosAccount`** is the only resource that every account is guaranteed to contain. ### AptosAccount module [](#aptosaccount-module) * **The AptosAccount module** is a Move module that contains the code for manipulating the administrative data held in a particular `AptosAccount.T` resource. * Code for checking or incrementing sequence numbers, withdrawing or depositing currency, and extracting gas deposits is included in the AptosAccount module. ### Aptos Devnet [](#aptos-devnet) * See [devnet](#devnet). ## B [](#b) ### Blocks [](#blocks) * On Aptos, blocks are a batch of [transactions](#transaction) committed at the same time. * Block number is analogous to “block height” in blockchain literature. * Transactions are referenced by ledger version rather than by block. ### BlockSTM [](#blockstm) * **BlockSTM** is the state-of-the-art dynamic parallelism execution engine developed by the Aptos Labs team. * Dynamic parallelism allows developers to flexibly write applications without facing design constraints of statically declaring write sets of transactions. * It has been adopted across the industry by multiple blockchains. * More details can be found in [the blog post](https://medium.com/aptoslabs/block-stm-how-we-execute-over-160k-transactions-per-second-on-the-aptos-blockchain-3b003657e4ba) and [presentation at a16z crypto](https://www.youtube.com/watch?v=2SE5tqPzhyw) ### Byzantine (Validator) [](#byzantine-validator) * A **validator** that does not follow the specification of the consensus protocol, and wishes to compromise the correct execution of the protocol. * BFT algorithms traditionally support up to one-third of the algorithm’s voting power being held by Byzantine validators. ### Byzantine Fault Tolerance (BFT) [](#byzantine-fault-tolerance-bft) * **Byzantine Fault Tolerance** (BFT) is the ability of a distributed system to provide safety and liveness guarantees in the presence of faulty, or “[Byzantine](https://en.wikipedia.org/wiki/Byzantine_fault),” validators below a certain threshold. * The Aptos blockchain uses AptosBFT, a consensus protocol based on [Jolteon](#jolteon). * BFT algorithms typically operate with a number of entities, collectively holding NNN votes (which are called “validators” in the Aptos network’s application of the system). * NNN is chosen to withstand some number of validators holding fff votes, which might be malicious. * In this configuration, NNN is typically set to 3f+13f + 13f+1. Validators holding up to fff votes will be allowed to be faulty — offline, malicious, slow, etc. As long as 2f+12f + 12f+1 votes are held by [honest](#honest-validator) validators, they will be able to reach consensus on consistent decisions. * This implies that BFT consensus protocols can function correctly, even if up to one-third of the voting power is held by validators that are compromised or fail. ## C [](#c) ### CLI [](#cli) * **Command line interface** refers to the Aptos CLI used for developing on the Aptos blockchain, operating nodes, and debugging issues. Find out more at [the Aptos CLI page](/build/cli). ### Client [](#client) * **Client** is software that receives information from the blockchain and manages transactions. Clients interact with the blockchain through the Aptos nodes. ### Code Labs [](#code-labs) * **Code labs and tutorials** depict various workflows - such as the use of the Aptos CLI in minting non-fungible tokens (NFTs) - in order for users to understand how the process works and employ related functions in their code. If users have the necessary funds in their accounts, they can follow the same code lab and tutorial steps used in devnet, testnet and mainnet networks. ### Consensus [](#consensus) * **Consensus** is a component of a validator. * The consensus component is responsible for coordination and agreement amongst all validators on the block of transactions to be executed, their order, and the execution results. * The Aptos blockchain is formed with these agreed-upon transactions and their corresponding execution results. * The consensus component is accountable for achieving security, trust, and agreement among all validators on the Aptos blockchain. ### Consensus Protocol [](#consensus-protocol) * A **consensus protocol** is collectively executed by n validators to accept or reject a transaction and to agree on the ordering of transactions and execution results. * See [BFT](#byzantine-fault-tolerance-bft). ## D [](#d) ### Dapps [](#dapps) * **Decentralized applications (dapps)** are programs or digital applications that run on the Aptos blockchain autonomously. Smart contracts are commonly used to achieve this function. ### Devnet [](#devnet) * The **Aptos devnet** is a publicly deployed instance of the Aptos network that runs using a set of validator test nodes. * The devnet is a demonstration of the Aptos network that is built for experimenting with new ideas * The devnet simulates a digital payment system and the coins on the devnet have _no real world value_. * The devnet is the network by which developers are given the opportunity to test given protocols. It is similar to testnet as it operates independently of the mainnet yet is reset weekly. ## E [](#e) ### Ed25519 [](#ed25519) * **Ed25519** is our supported digital signature scheme. * More specifically, the Aptos network uses the PureEdDSA scheme over the Ed25519 curve, as defined in RFC 8032. ### Epoch [](#epoch) * An **epoch** is the period of time between reconfigurations of the validator set and other administrative actions by the blockchain. On Aptos mainnet currently, it is every 2 hours. ### Event [](#event) * An **event** is the user-facing representation of the effects of executing a transaction. * A transaction may be designed to emit any number of events as a list. For example, a `Coin` transfer emits a `WithdrawEvent` for the sender account and a `DepositEvent` for the recipient account. * In the Aptos protocol, events provide evidence that the successful execution of a transaction resulted in a specific effect. The `DepositEvent` (in the above example) allows the recipient to confirm that a payment was received into their account. * Events are persisted on the blockchain and are used to answer queries by [clients](#client). ### Execution [](#execution) * **Execution** in the Aptos blockchain is an Aptos node component that manages the block of transactions. The execution component stores successful transactions. ### Expiration Time [](#expiration-time) A transaction ceases to be valid after its **expiration time**. If it is assumed that: * Time\_CTime\\\_CTime\_C is the current time that is agreed upon between validators (Time\_CTime\\\_CTime\_C is not the local time of the client); * Time\_ETime\\\_ETime\_E is the expiration time of a transaction T\_NT\\\_NT\_N; and * Time\_C\>Time\_ETime\\\_C > Time\\\_ETime\_C\>Time\_E and transaction T\_NT\\\_NT\_N has not been included in the blockchain, then there is a guarantee that T\_NT\\\_NT\_N will never be included in the blockchain. ## F [](#f) ### Faucet [](#faucet) * The **faucet** is a service that mints APT on devnet. For testnet see the [mint page](/network/faucet). * APT on devnet and testnet has no real world value, it is only for development purposes. * To use a faucet, see [Faucet API](/build/apis/faucet-api). ### Fullnodes [](#fullnodes) * **Fullnodes** are clients that ensure data are stored up-to-date on the network. They replicate blockchain state and transactions from other fullnodes and validator nodes. ### Fungible Asset [](#fungible-asset) * A **fungible asset** is an asset, such as a currency, share, in-game resource, etc., that is interchangeable with another identical asset without any loss in its value. For example, APT is a fungible asset because you can exchange one APT for another. * Follow the [Asset Standards](/build/smart-contracts/aptos-standards#asset-standards) to create fungible assets on the Aptos blockchain. * Next generation of the Coin standard that addresses shortcomings of `aptos_framework::coin` such as lack of guaranteed enforcement of freeze and burn and advanced functionalities such as programmable transfers, e.g., approve in ERC-20. ### Fungible Token [](#fungible-token) * For the legacy Aptos Token Standard (aptos\_token::token), a **fungible token** is a token that is interchangeable with other identical tokens (i.e., tokens that share the same `TokenId`). This means the tokens have the same `creator address`, `collection name`, `token name`, and `property version`. * For the Aptos Digital Asset Standard (aptos\_token\_objects::token), a \* _fungible token_\* is a fungible asset with metadata object that includes a Digital Asset resource. ### Fungible Unit [](#fungible-unit) * A **fungible unit** is an individual unit of a fungible asset. These units are identical and interchangeable without any loss in value. For example, each [Octa](#octa) (the smallest unit of APT) is a fungible unit. ## G [](#g) ### Gas [](#gas) * **Gas** is a way to pay for computation and storage on a blockchain network. All transactions on the Aptos network cost a certain amount of gas. * The gas required for a transaction depends on the size of the transaction, the computational cost of executing the transaction, and the amount of additional global state created by the transaction (e.g., if new accounts are created). * The purpose of gas is regulating demand for the limited computational and storage resources of the validators, including preventing denial of service ( DoS) attacks. See [Gas and Storage Fees](/network/blockchain/gas-txn-fee) for more information. ### Gas Unit Price [](#gas-unit-price) * Each transaction specifies the **gas unit price** the sender is willing to pay per unit of gas. * The price of gas required for a transaction depends on the current demand for usage of the network. * Gas price is expressed in [Octas](#octa). See [Gas and Storage Fees](/network/blockchain/gas-txn-fee) for more information. ## H [](#h) ### Honest (Validator) [](#honest-validator) * **Honesty** means a validator that faithfully executes the consensus protocol and is not Byzantine. ## I [](#i) ### Indexer [](#indexer) * **[Indexer](/build/indexer)** is the component of Aptos that retrieves, processes, and efficiently stores raw data in the database to provide speedy access to the Aptos blockchain state. * At a high level, indexer gets data from a gRPC stream and runs processors to transform raw blockchain data and serve transformed data via GraphQL endpoint. ## J [](#j) ### Jolteon [](#jolteon) * **Jolteon** is a recent proposal for a [BFT](#byzantine-fault-tolerance-bft) consensus protocol. * AptosBFT, the Aptos network’s consensus algorithm, is based on Jolteon. * It simplifies the reasoning about safety, and it addresses some performance limitations of previous consensus protocols. In particular, it reduces latency by 33% compared to HotStuff. ## L [](#l) ### Leader [](#leader) * A **leader** is a validator that proposes a block of transactions for the consensus protocol. * In leader-based protocols, nodes must agree on a leader to make progress. * Leaders are selected by a function that takes the current [round number](#round-number) as input. ## M [](#m) ### Mainnet [](#mainnet) * **Mainnet** refers to a working, fully-operational blockchain. A mainnet network has been fully deployed and performs the functionality of transferring digital currency from a sender to a recipient. ### Maximum Gas Amount [](#maximum-gas-amount) * The **Maximum Gas Amount** of a transaction is the maximum gas amount in gas units that the sender is ready to pay for the transaction. * The transaction can be successfully executed only if the gas used does not exceed the maximum gas amount. * The gas charged is equal to the gas price multiplied by units of gas required to process this transaction. * If the transaction runs out of gas while it is being executed or the account runs out of balance during execution, then the sender will be charged for gas used and the transaction will fail. See [Gas and Storage Fees](/network/blockchain/gas-txn-fee) for more information. ### Mempool [](#mempool) * **Mempool** is one of the components of the validator. It holds an in-memory buffer of transactions that have been submitted but not yet agreed upon and executed. Mempool receives transactions from other [full nodes](#fullnodes). * Transactions in the mempool of a validator are added from the JSON-RPC Service of the current node and from the mempool of other Aptos nodes. * When the current validator is the leader, its consensus component pulls the transactions from its mempool and proposes the order of the transactions that form a block. The validator quorum then votes on the proposal. ### Merkle Trees [](#merkle-trees) * **Merkle tree** is a type of authenticated data structure that allows for efficient verification of data integrity and updates. * The Aptos network treats the entire blockchain as a single data structure that records the history of transactions and states over time. * The [Merkle tree](https://en.wikipedia.org/wiki/Merkle_tree) implementation simplifies the work of apps accessing the blockchain. It allows apps to: * Read any data from any point in time. * Verify the integrity of the data using a unified framework. ### Merkle Accumulator [](#merkle-accumulator) * The **[Merkle Accumulator](https://www.usenix.org/legacy/event/sec09/tech/full_papers/crosby.pdf)** is an _append-only_ Merkle tree that the Aptos blockchain uses to store the ledger. * A Merkle accumulator can provide proofs that a transaction was included in the chain (“proof of inclusion”). * They are also called “history trees” in literature. ### Module [](#module) * A **module** in the Move programming language may either be a program or library that can create, transfer, or store assets. ### Move [](#move) * **Move** is a new programming language that implements all the transactions on the Aptos blockchain. * It has two different kinds of code — [Move scripts](#move-script) and [Move modules](#move-module). * Move is a safe and secure programming language for web3 that emphasizes access control and scarcity. It is the programming language used to build the Aptos blockchain. You can read more about it in [Move on Aptos](/network/blockchain/move). ### Move Bytecode [](#move-bytecode) * Move programs are compiled into **Move bytecode**. * Move bytecode is used to express Move scripts and Move modules. ### Move Module [](#move-module) * A **Move module** defines the rules for updating the global state of the Aptos blockchain. * In the Aptos protocol, a Move module is a **smart contract**. * Each user-submitted transaction includes a Move script. The Move script invokes procedures of one or more Move modules to update the global state of the blockchain according to the rules. ### Move Resources [](#move-resources) * **Move resources** contain data that can be accessed according to the \* _procedures_\* declared in a Move **module.** * Move resources can never be copied, reused, or lost. This protects Move programmers from accidentally or intentionally losing track of a resource. ### Move Script [](#move-script) * Each transaction submitted by a user includes a **Move script**. * These transactions, also known as Move scripts, represent the operations a client submits to a validator. * The operation could be a request to move coins from user A to user B, or it could involve interactions with published [Move modules](#move-module) (smart contracts). * The Move script is an arbitrary program that interacts with resources published in the global storage of the Aptos blockchain by calling the procedures of a module. It encodes the logic for a transaction. * A single Move script can send funds to multiple recipients and invoke procedures from several different modules. * A Move script **is not** stored in the global state and cannot be invoked by other Move scripts. It is a single-use program. To see example uses of Move scripts, follow [Move scripts](/build/smart-contracts/scripts/script-tutorial). ### Move Virtual Machine (MVM) [](#move-virtual-machine-mvm) * The **Move virtual machine** executes Move scripts written in [Move bytecode](#move-bytecode) to produce an execution result. This result is used to update the blockchain **state**. * The virtual machine is part of a [validator](#validator). * The Move virtual machine (MoveVM) processes each validator node that translates transactions along with the current blockchain ledger state to produce a changeset as input or storage delta as output. ## N [](#n) ### Node [](#node) * A **node** is a peer entity of the Aptos network that tracks the state of the Aptos blockchain. * An Aptos node consists of logical components. [Mempool](#mempool), [consensus](#consensus), and the [Move virtual machine](#move-virtual-machine-mvm) are examples of node components. ### Nonce [](#nonce) * **Nonce** is a number only used once, a random or semi-random number that is generated for a specific use for authentication protocols and cryptographic hash functions. ## O [](#o) ### Octa [](#octa) * An **Octa** is the smallest unit of [APT](#apt). 1 APT = 108 Octas. ### Open-Source Community [](#open-source-community) * **Open-source community** is a term used for a group of developers who work on open-source software. If you’re reading this glossary, then you are part of the Aptos project’s developer community. ## P [](#p) ### Proof [](#proof) * A **proof** is a way to verify the accuracy of data in the blockchain. * Every operation in the Aptos blockchain can be verified cryptographically that it is indeed correct and that data has not been omitted. * For example, if a user queries the information within a particular executed transaction, they will be provided with a cryptographic proof that the data returned to them is correct. ### Proof-of-Stake (PoS) [](#proof-of-stake-pos) **Proof-of-Stake (PoS)** is a security mechanism that serves in confirming the uniqueness and legitimacy of blockchain transactions. The PoS consensus mechanism is leveraged by the Aptos blockchain powered by a network of validators, which in turn update the system and process transactions. ## Q [](#q) ### Quorum Store [](#quorum-store) * **Quorum Store** is the component that disseminates transactions (in batches) within the validator set. * It significantly improves consensus throughput by removing the leader bottleneck. * It decouples data dissemination from metadata ordering, allowing validators to disseminate data asynchronously in parallel. * More details can be found in the [blog post](https://medium.com/aptoslabs/quorum-store-how-consensus-horizontally-scales-on-the-aptos-blockchain-988866f6d5b0) ## R [](#r) ### Randapp [](#randapp) * A [dapp](#dapps) that uses randomness for its functionality. ### Resource Account [](#resource-account) * A **resource account** is used to manage resources independent of an account managed by a user. For example, a developer may use a resource account to manage an account for module publishing, say managing a contract. * The contract itself does not require a signer post initialization. A resource account gives you the means for the module to provide a signer to other modules and sign transactions on behalf of the module. See [Resource accounts](/build/smart-contracts/resource-accounts) for instructions on use. ### REST API Service [](#rest-api-service) * The **REST API Service** component is the external interface of an Aptos node. Any incoming client request, such as submitted transactions or queries, must first go through the REST Service. A client needs to go through the REST Service component to access storage or any other component in the system. This filters requests and protects the system. * Whenever a client submits a new transaction, the REST Service passes it to [mempool](#mempool). ### Round [](#round) * A **round** consists of achieving consensus on a block of transactions and their execution results. ### Round Number [](#round-number) * A **round number** is a shared counter used to select leaders during an [epoch](#epoch) of the consensus protocol. ## S [](#s) ### SDKs [](#sdks) * Aptos **software development kits (SDKs)** are sets of tools that enable a developer to quickly create a custom app on the Aptos platform. Find out more at [Use the Aptos SDKs](/build/sdks). ### Sequence Number [](#sequence-number) * The **sequence number** for an account indicates the number of transactions that have been submitted and committed on chain from that account. It is incremented every time a transaction sent from that account is executed or aborted and stored in the blockchain. * A transaction is executed only if it matches the current sequence number for the sender account. This helps sequence multiple transactions from the same sender and prevents replay attacks. * If the current sequence number of an account A is X, then a transaction T on account A will only be executed if T’s sequence number is X. * These transactions will be held in mempool until they are the next sequence number for that account (or until they expire). * When the transaction is applied, the sequence number of the account will become X+1. The account has a strictly increasing sequence number. ### Sender [](#sender) * _Alternate name_: Sender address. * **Sender** is the address that originates the transaction. A transaction must be signed by the sender but can have more than one signer. ### Shoal [](#shoal) * Method for decreasing latency for BFT protocols. See the [Shoal paper](https://arxiv.org/pdf/2306.03058.pdf) ### Smart Contract [](#smart-contract) * **Smart contract** refers to a computer program that automatically and directly carries out the contract’s terms. * See [Move Module](#move-module) for related details. ### State [](#state) * A **state** in the Aptos protocol is a snapshot of the distributed database. * A transaction modifies the database and produces a new and updated state. ### State Root Hash [](#state-root-hash) * **State root hash** is a [Merkle hash](https://en.wikipedia.org/wiki/Merkle_tree) over all keys and values the state of the Aptos blockchain at a given version. ## T [](#t) ### Table [](#table) * A [**table**](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-stdlib/doc/table.md) implements the Table type and in Aptos is used to store information as key-value data within an account at large scale. See [`table.move`](https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-stdlib/sources/table.move) for the associated Aptos source file. ### Testnet [](#testnet) * **Testnet** describes the Aptos network that is not fully functional yet more stable than devnet; it is an alternative network to mainnet to be used for testing. ### Tokens [](#tokens) * **Tokens** are digital units of value issued on a blockchain. They can be redeemed for assets or value held. Tokens can be of the types: Fungible Token (FT), Non-Fungible Token (NFT), and Semi-Fungible Token (SFT). ### Transaction [](#transaction) * A raw **transaction** contains the following fields: * [Sender (account address)](#account-address) * [Move script](#move-script) * [Gas price](#gas-unit-price) * [Maximum gas amount](#maximum-gas-amount) * [Sequence number](#sequence-number) * [Expiration time](#expiration-time) * A signed transaction is a raw transaction with the digital signature. * An executed transaction changes the state of the Aptos blockchain. ### Transaction Script [](#transaction-script) * See [Move script](#move-script) ## V [](#v) ### Validator [](#validator) * _Alternate name_: Validators. * A **validator** is an entity of the Aptos ecosystem that validates on the Aptos blockchain. It receives requests from clients and runs consensus, execution, and storage. * A validator maintains the history of all the transactions on the blockchain. * Internally, a validator needs to keep the current state, to execute transactions, and to calculate the next state. * Aptos validators are in charge of verifying transactions. ### Validator Nodes [](#validator-nodes) * **Validator nodes** are a unique class of fullnodes that take part in consensus, specifically a Byzantine Fault Tolerance (BFT) consensus protocol in Aptos. Validators agree upon transactions to be added to the Aptos blockchain as well as the order in which they are added. ### Version [](#version) * A **version** is a sequentially increasing number that increments for every [transaction](#transaction). * On aptos, transactions are globally ordered and every transaction has a version (often called “height” in blockchain literature.) * Transaction version 0 is the first transaction (genesis transaction), and a transaction version 100 is the 101st transaction in the blockchain. ## W [](#w) ### Well-Formed Transaction [](#well-formed-transaction) An Aptos transaction is **well-formed** if each of the following conditions are true for the transaction: * The transaction has a valid signature. * An account exists at the sender address. * It includes a public key, and the hash of the public key matches the sender account’s authentication key. * The sequence number of the transaction matches the sender account’s sequence number. * The sender account’s balance is greater than the [maximum gas amount](#maximum-gas-amount). * The expiration time of the transaction has not passed.