Skip to content

Creating and Managing Accounts

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.

The most common way to create a new account is with Ed25519Account::generate(), which produces a random Ed25519 key pair:

use aptos_sdk::account::Ed25519Account;
let account = Ed25519Account::generate();
println!("Address: {}", account.address());
println!("Public Key: {}", account.public_key());

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.

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):

use aptos_sdk::account::{Secp256k1Account, Secp256r1Account};
// Generate a Secp256k1 account (Bitcoin/Ethereum compatible)
let secp256k1_account = Secp256k1Account::generate();
println!("Secp256k1 Address: {}", secp256k1_account.address());
// Generate a Secp256r1 account (WebAuthn/passkey compatible)
let secp256r1_account = Secp256r1Account::generate();
println!("Secp256r1 Address: {}", secp256r1_account.address());

The following table summarizes the available signing schemes:

SchemeAccount TypeFeature FlagDefaultTypical Use Cases
Ed25519Ed25519Accounted25519YesGeneral purpose, most common
Secp256k1Secp256k1Accountsecp256k1YesBitcoin/Ethereum ecosystem compatibility
Secp256r1 (P-256)Secp256r1Accountsecp256r1YesWebAuthn, passkeys, secure enclaves
BLS12-381Bls12381AccountblsNoAggregate signatures, validator operations

To use BLS12-381, enable the bls feature in your Cargo.toml:

[dependencies]
aptos-sdk = { git = "https://github.com/aptos-labs/aptos-rust-sdk", package = "aptos-sdk", features = ["bls"] }

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:

use aptos_sdk::account::Ed25519Account;
let private_key_hex = "0xYOUR_PRIVATE_KEY_HEX";
let account = Ed25519Account::from_private_key_hex(private_key_hex)?;
println!("Loaded account: {}", account.address());

A safer pattern is to load the key from an environment variable at runtime:

use aptos_sdk::account::Ed25519Account;
let private_key_hex = std::env::var("APTOS_PRIVATE_KEY")
.expect("APTOS_PRIVATE_KEY environment variable must be set");
let account = Ed25519Account::from_private_key_hex(&private_key_hex)?;

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.

Use generate_with_mnemonic() to create a brand-new account along with its mnemonic phrase:

use aptos_sdk::account::Ed25519Account;
let (account, mnemonic) = Ed25519Account::generate_with_mnemonic()?;
println!("Address: {}", account.address());
println!("Mnemonic: {}", mnemonic);

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:

use aptos_sdk::account::Ed25519Account;
let mnemonic = "your twelve or twenty four word mnemonic phrase goes here ...";
// Derive the first account (index 0)
let account_0 = Ed25519Account::from_mnemonic(mnemonic, 0)?;
println!("Account 0: {}", account_0.address());
// Derive the second account (index 1)
let account_1 = Ed25519Account::from_mnemonic(mnemonic, 1)?;
println!("Account 1: {}", account_1.address());

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:

use aptos_sdk::account::Ed25519Account;
let mnemonic = "your mnemonic phrase ...";
// Derive 10 accounts from the same mnemonic
for index in 0..10 {
let account = Ed25519Account::from_mnemonic(mnemonic, index)?;
println!("Account {}: {}", index, account.address());
}

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.

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:

use aptos_sdk::account::{AnyAccount, Ed25519Account, Secp256k1Account};
let ed25519 = Ed25519Account::generate();
let secp256k1 = Secp256k1Account::generate();
// Store different account types in the same collection
let accounts: Vec<AnyAccount> = vec![
AnyAccount::Ed25519(ed25519),
AnyAccount::Secp256k1(secp256k1),
];
for account in &accounts {
println!("Address: {}", account.address());
}

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.

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.

On testnet and devnet, you can use the built-in faucet integration (requires the faucet feature, which is on by default):

use aptos_sdk::{Aptos, AptosConfig};
use aptos_sdk::account::Ed25519Account;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let aptos = Aptos::new(AptosConfig::testnet())?;
let account = Ed25519Account::generate();
// Fund an existing account with 100_000_000 octas (1 APT)
aptos.fund_account(account.address(), 100_000_000).await?;
println!("Funded account: {}", account.address());
Ok(())
}

For convenience, the SDK also offers create_funded_account(), which generates a new account and funds it in a single call:

use aptos_sdk::{Aptos, AptosConfig};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let aptos = Aptos::new(AptosConfig::testnet())?;
// Generate and fund a new Ed25519 account in one step
let account = aptos.create_funded_account(100_000_000).await?;
println!("New funded account: {}", account.address());
Ok(())
}