|
| 1 | +--- |
| 2 | +title: "Creating and Managing Accounts" |
| 3 | +description: "Learn how to generate, load, and manage Aptos accounts using the Rust SDK with different signing schemes" |
| 4 | +sidebar: |
| 5 | + label: "Managing Accounts" |
| 6 | +--- |
| 7 | + |
| 8 | +import { Aside } from '@astrojs/starlight/components'; |
| 9 | + |
| 10 | +The Aptos Rust SDK provides several account types for managing on-chain identities. All account types implement the `Account` trait, which provides a common interface for signing transactions and deriving addresses. This page covers how to generate new accounts, load existing ones, and fund them on the network. |
| 11 | + |
| 12 | +## Generating Accounts |
| 13 | + |
| 14 | +The most common way to create a new account is with `Ed25519Account::generate()`, which produces a random Ed25519 key pair: |
| 15 | + |
| 16 | +```rust |
| 17 | +use aptos_sdk::account::Ed25519Account; |
| 18 | + |
| 19 | +let account = Ed25519Account::generate(); |
| 20 | +println!("Address: {}", account.address()); |
| 21 | +println!("Public Key: {}", account.public_key()); |
| 22 | +``` |
| 23 | + |
| 24 | +The `address()` method returns the on-chain address derived from the public key, and `public_key()` returns the public half of the key pair. The private key never leaves the account object unless you explicitly export it. |
| 25 | + |
| 26 | +## Other Signing Schemes |
| 27 | + |
| 28 | +Beyond Ed25519, the SDK supports additional cryptographic signing schemes. Each is gated behind a Cargo feature flag that is enabled by default (except BLS12-381): |
| 29 | + |
| 30 | +```rust |
| 31 | +use aptos_sdk::account::{Secp256k1Account, Secp256r1Account}; |
| 32 | + |
| 33 | +// Generate a Secp256k1 account (Bitcoin/Ethereum compatible) |
| 34 | +let secp256k1_account = Secp256k1Account::generate(); |
| 35 | +println!("Secp256k1 Address: {}", secp256k1_account.address()); |
| 36 | + |
| 37 | +// Generate a Secp256r1 account (WebAuthn/passkey compatible) |
| 38 | +let secp256r1_account = Secp256r1Account::generate(); |
| 39 | +println!("Secp256r1 Address: {}", secp256r1_account.address()); |
| 40 | +``` |
| 41 | + |
| 42 | +The following table summarizes the available signing schemes: |
| 43 | + |
| 44 | +| Scheme | Account Type | Feature Flag | Default | Typical Use Cases | |
| 45 | +| ----------------- | ------------------ | ------------ | ------- | ------------------------------------------ | |
| 46 | +| Ed25519 | `Ed25519Account` | `ed25519` | Yes | General purpose, most common | |
| 47 | +| Secp256k1 | `Secp256k1Account` | `secp256k1` | Yes | Bitcoin/Ethereum ecosystem compatibility | |
| 48 | +| Secp256r1 (P-256) | `Secp256r1Account` | `secp256r1` | Yes | WebAuthn, passkeys, secure enclaves | |
| 49 | +| BLS12-381 | `Bls12381Account` | `bls` | No | Aggregate signatures, validator operations | |
| 50 | + |
| 51 | +To use BLS12-381, enable the `bls` feature in your `Cargo.toml`: |
| 52 | + |
| 53 | +```toml filename="Cargo.toml" |
| 54 | +[dependencies] |
| 55 | +aptos-sdk = { git = "https://github.com/aptos-labs/aptos-rust-sdk", package = "aptos-sdk", features = ["bls"] } |
| 56 | +``` |
| 57 | + |
| 58 | +## Loading from a Private Key |
| 59 | + |
| 60 | +If you already have a private key (for example, from an existing wallet or a configuration file), you can reconstruct the account object from its hex-encoded private key: |
| 61 | + |
| 62 | +```rust |
| 63 | +use aptos_sdk::account::Ed25519Account; |
| 64 | + |
| 65 | +let private_key_hex = "0xYOUR_PRIVATE_KEY_HEX"; |
| 66 | +let account = Ed25519Account::from_private_key_hex(private_key_hex)?; |
| 67 | +println!("Loaded account: {}", account.address()); |
| 68 | +``` |
| 69 | + |
| 70 | +<Aside type="caution" title="Never Hardcode Private Keys"> |
| 71 | + Do not embed private keys directly in your source code. Store them in environment variables, secret managers, or encrypted configuration files. Hardcoded keys that are committed to version control can lead to irreversible loss of funds. |
| 72 | +</Aside> |
| 73 | + |
| 74 | +A safer pattern is to load the key from an environment variable at runtime: |
| 75 | + |
| 76 | +```rust |
| 77 | +use aptos_sdk::account::Ed25519Account; |
| 78 | + |
| 79 | +let private_key_hex = std::env::var("APTOS_PRIVATE_KEY") |
| 80 | + .expect("APTOS_PRIVATE_KEY environment variable must be set"); |
| 81 | +let account = Ed25519Account::from_private_key_hex(&private_key_hex)?; |
| 82 | +``` |
| 83 | + |
| 84 | +## Loading from a Mnemonic Phrase |
| 85 | + |
| 86 | +The SDK supports BIP-39 mnemonic phrases when the `mnemonic` feature is enabled (on by default). This allows you to generate deterministic accounts from a 12- or 24-word recovery phrase. |
| 87 | + |
| 88 | +### Generating a New Mnemonic |
| 89 | + |
| 90 | +Use `generate_with_mnemonic()` to create a brand-new account along with its mnemonic phrase: |
| 91 | + |
| 92 | +```rust |
| 93 | +use aptos_sdk::account::Ed25519Account; |
| 94 | + |
| 95 | +let (account, mnemonic) = Ed25519Account::generate_with_mnemonic()?; |
| 96 | +println!("Address: {}", account.address()); |
| 97 | +println!("Mnemonic: {}", mnemonic); |
| 98 | +``` |
| 99 | + |
| 100 | +<Aside type="caution"> |
| 101 | + Store the mnemonic phrase securely. Anyone with access to the mnemonic can reconstruct the account and control its funds. |
| 102 | +</Aside> |
| 103 | + |
| 104 | +### Restoring from an Existing Mnemonic |
| 105 | + |
| 106 | +To restore an account from a mnemonic phrase, use `from_mnemonic()`. You can specify a derivation index to derive different accounts from the same mnemonic: |
| 107 | + |
| 108 | +```rust |
| 109 | +use aptos_sdk::account::Ed25519Account; |
| 110 | + |
| 111 | +let mnemonic = "your twelve or twenty four word mnemonic phrase goes here ..."; |
| 112 | + |
| 113 | +// Derive the first account (index 0) |
| 114 | +let account_0 = Ed25519Account::from_mnemonic(mnemonic, 0)?; |
| 115 | +println!("Account 0: {}", account_0.address()); |
| 116 | + |
| 117 | +// Derive the second account (index 1) |
| 118 | +let account_1 = Ed25519Account::from_mnemonic(mnemonic, 1)?; |
| 119 | +println!("Account 1: {}", account_1.address()); |
| 120 | +``` |
| 121 | + |
| 122 | +### Deriving Multiple Accounts |
| 123 | + |
| 124 | +A single mnemonic phrase can produce an unlimited number of deterministic accounts by varying the derivation index. This is useful for applications that manage many accounts from a single seed: |
| 125 | + |
| 126 | +```rust |
| 127 | +use aptos_sdk::account::Ed25519Account; |
| 128 | + |
| 129 | +let mnemonic = "your mnemonic phrase ..."; |
| 130 | + |
| 131 | +// Derive 10 accounts from the same mnemonic |
| 132 | +for index in 0..10 { |
| 133 | + let account = Ed25519Account::from_mnemonic(mnemonic, index)?; |
| 134 | + println!("Account {}: {}", index, account.address()); |
| 135 | +} |
| 136 | +``` |
| 137 | + |
| 138 | +Each index always produces the same account, so you can reliably reconstruct any account as long as you know the mnemonic and the index that was used. |
| 139 | + |
| 140 | +## The `AnyAccount` Enum |
| 141 | + |
| 142 | +When you need to work with accounts of different signing schemes in a uniform way, the SDK provides the `AnyAccount` enum. This is a polymorphic wrapper that implements the `Account` trait regardless of the underlying key type: |
| 143 | + |
| 144 | +```rust |
| 145 | +use aptos_sdk::account::{AnyAccount, Ed25519Account, Secp256k1Account}; |
| 146 | + |
| 147 | +let ed25519 = Ed25519Account::generate(); |
| 148 | +let secp256k1 = Secp256k1Account::generate(); |
| 149 | + |
| 150 | +// Store different account types in the same collection |
| 151 | +let accounts: Vec<AnyAccount> = vec![ |
| 152 | + AnyAccount::Ed25519(ed25519), |
| 153 | + AnyAccount::Secp256k1(secp256k1), |
| 154 | +]; |
| 155 | + |
| 156 | +for account in &accounts { |
| 157 | + println!("Address: {}", account.address()); |
| 158 | +} |
| 159 | +``` |
| 160 | + |
| 161 | +`AnyAccount` is particularly useful when building applications that support multiple signing schemes or when you need to pass accounts through a generic interface without knowing the concrete type at compile time. |
| 162 | + |
| 163 | +## Funding Accounts |
| 164 | + |
| 165 | +A newly generated account exists only as a local key pair until it is registered on the network. To make the network aware of an account, you must fund it with APT. |
| 166 | + |
| 167 | +### Using the Faucet on Testnet or Devnet |
| 168 | + |
| 169 | +On testnet and devnet, you can use the built-in faucet integration (requires the `faucet` feature, which is on by default): |
| 170 | + |
| 171 | +```rust |
| 172 | +use aptos_sdk::{Aptos, AptosConfig}; |
| 173 | +use aptos_sdk::account::Ed25519Account; |
| 174 | + |
| 175 | +#[tokio::main] |
| 176 | +async fn main() -> anyhow::Result<()> { |
| 177 | + let aptos = Aptos::new(AptosConfig::testnet())?; |
| 178 | + |
| 179 | + let account = Ed25519Account::generate(); |
| 180 | + |
| 181 | + // Fund an existing account with 100_000_000 octas (1 APT) |
| 182 | + aptos.fund_account(account.address(), 100_000_000).await?; |
| 183 | + println!("Funded account: {}", account.address()); |
| 184 | + |
| 185 | + Ok(()) |
| 186 | +} |
| 187 | +``` |
| 188 | + |
| 189 | +### Creating a Pre-Funded Account |
| 190 | + |
| 191 | +For convenience, the SDK also offers `create_funded_account()`, which generates a new account and funds it in a single call: |
| 192 | + |
| 193 | +```rust |
| 194 | +use aptos_sdk::{Aptos, AptosConfig}; |
| 195 | + |
| 196 | +#[tokio::main] |
| 197 | +async fn main() -> anyhow::Result<()> { |
| 198 | + let aptos = Aptos::new(AptosConfig::testnet())?; |
| 199 | + |
| 200 | + // Generate and fund a new Ed25519 account in one step |
| 201 | + let account = aptos.create_funded_account(100_000_000).await?; |
| 202 | + println!("New funded account: {}", account.address()); |
| 203 | + |
| 204 | + Ok(()) |
| 205 | +} |
| 206 | +``` |
| 207 | + |
| 208 | +<Aside type="note" title="Faucet Availability"> |
| 209 | + The faucet is only available on **devnet** and **testnet**. On mainnet, you must acquire APT through an exchange or transfer from another account. |
| 210 | +</Aside> |
0 commit comments