| name | ts-sdk-account |
| description | How to create and use Account (signer) in @aptos-labs/ts-sdk. Covers Account.generate(), fromPrivateKey(), fromDerivationPath(), Ed25519 vs SingleKey vs MultiKey vs Keyless, serialization (fromHex/toHex). Triggers on: 'Account.generate', 'Account.fromPrivateKey', 'Ed25519PrivateKey', 'SDK account', 'mnemonic', 'SingleKeyAccount', 'KeylessAccount'. |
| metadata | {"category":"sdk","tags":["typescript","sdk","account","signer","private-key","ed25519","keyless"],"priority":"high"} |
TypeScript SDK: Account (Signer)
Purpose
Guide creation and use of Account (signer) in @aptos-labs/ts-sdk. An Account holds address + key material and can sign transactions and messages. Creating an Account does NOT create the account on-chain; use faucet or transfer to fund it.
ALWAYS
- Use
Account.generate() or Account.fromPrivateKey() only in server/script – never in frontend; use wallet adapter for end users.
- Load private keys from env (e.g.
process.env.PRIVATE_KEY) on server – never hardcode.
- Use
account.accountAddress when building transactions – pass as sender/secondary signers.
- Use
aptos.signAndSubmitTransaction({ signer: account, transaction }) with the same Account instance that holds the key.
NEVER
- Do not use
Account.generate() or raw private keys in browser/frontend – use wallet adapter.
- Do not hardcode private keys in source or commit to git.
- Do not confuse
Account (API namespace) with Account (signer class) – API is aptos.account.*; signer is the class from Account module (e.g. Account.fromPrivateKey).
Account types (signing schemes)
| Type | Class | Use case |
|---|
| Ed25519 (legacy) | Ed25519Account | Single Ed25519 key, legacy auth |
| SingleKey | SingleKeyAccount | Ed25519 or Secp256k1, unified auth |
| MultiKey | MultiKeyAccount | Multi-sig |
| Keyless | KeylessAccount | Keyless (e.g. OIDC) |
| Federated Keyless | FederatedKeylessAccount | Federated keyless |
Generate new account (server/script only)
import { Account, SigningSchemeInput } from "@aptos-labs/ts-sdk";
const ed25519Account = Account.generate();
const singleKeyAccount = Account.generate({ scheme: SigningSchemeInput.Ed25519, legacy: false });
const secpAccount = Account.generate({ scheme: SigningSchemeInput.Secp256k1 });
const address = ed25519Account.accountAddress;
const pubKey = ed25519Account.publicKey;
From private key
import { Account, Ed25519PrivateKey, Secp256k1PrivateKey } from "@aptos-labs/ts-sdk";
const privateKeyHex = process.env.PRIVATE_KEY!;
const privateKey = new Ed25519PrivateKey(privateKeyHex);
const account = Account.fromPrivateKey({ privateKey });
const accountSingle = Account.fromPrivateKey({
privateKey: new Ed25519PrivateKey(privateKeyHex),
legacy: false,
});
const secpKey = new Secp256k1PrivateKey(process.env.SECP_KEY!);
const accountSecp = Account.fromPrivateKey({ privateKey: secpKey });
const accountWithAddr = Account.fromPrivateKey({
privateKey,
address: "0x...",
});
From mnemonic (derivation path)
import { Account } from "@aptos-labs/ts-sdk";
const mnemonic = "word1 word2 ... word12";
const path = "m/44'/637'/0'/0'/0'";
const acc = Account.fromDerivationPath({ mnemonic, path });
const accSingle = Account.fromDerivationPath({ mnemonic, path, legacy: false });
const accSecp = Account.fromDerivationPath({
scheme: SigningSchemeInput.Secp256k1,
mnemonic,
path,
});
Auth key (for rotation / lookup)
const authKey = Account.authKey({ publicKey: account.publicKey });
Serialization (toHex / fromHex)
Use when persisting or sending account (e.g. server-only, never expose private key to frontend):
import { Account, AccountUtils } from "@aptos-labs/ts-sdk";
const account = Account.generate();
const hex = AccountUtils.toHexString(account);
const restored = AccountUtils.fromHex(hex);
const edAccount = AccountUtils.ed25519AccountFromHex(hex);
const singleAccount = AccountUtils.singleKeyAccountFromHex(hex);
const multiAccount = AccountUtils.multiKeyAccountFromHex(hex);
const keylessAccount = AccountUtils.keylessAccountFromHex(hex);
Signing
const sig = account.sign(messageHex);
const txSig = account.signTransaction(rawTransaction);
const auth = account.signWithAuthenticator(messageHex);
Verify signature
const ok = account.verifySignature({ message: messageHex, signature: sig });
const okAsync = await account.verifySignatureAsync({
aptosConfig: aptos.config,
message: messageHex,
signature: sig,
});
Derive account from private key (on-chain lookup)
When the same key may have multiple on-chain accounts (e.g. after rotation), use internal derivation + lookup:
const accounts = await aptos.deriveOwnedAccountsFromSigner({
signer: account,
});
Common mistakes
| Mistake | Correct approach |
|---|
Using Account.generate() in frontend | Use wallet adapter; generate only in server/script |
| Hardcoding private key | Load from process.env (server) and never commit |
Using aptos.account as signer | aptos.account is API namespace; signer is Account.fromPrivateKey() / Account.generate() |
| Expecting account to exist on-chain after generate | Fund with faucet or transfer first |
References