Skip to content
🎉 Welcome to the new Aptos Docs! Click here to submit an issue.
BuildGuidesYour First Transaction

Your First Transaction

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

This tutorial builds on concepts from the Aptos blockchain. If you’re new to blockchain development, don’t worry - we’ll explain key concepts along the way.

1. Setting Up Your Environment

Before we can create transactions, we need to set up our development environment with the necessary tools and SDKs.

Install the TypeScript SDK

Install the TypeScript SDK using your preferred package manager:

Terminal
npm install @aptos-labs/ts-sdk

Create a project directory

Create a new directory for your project:

Terminal
mkdir my-first-transaction
cd my-first-transaction

Create a new file

Create a new file named transaction.ts:

Terminal
touch transaction.ts

2. Creating Test Accounts

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

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:

transaction.ts
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);

We’re connecting to the Aptos devnet, which is a test network where you can experiment without using real coins. The devnet is reset periodically, so don’t store anything important there.

Generate accounts

Now let’s create two accounts: Alice (sender) and Bob (receiver):

Add this code inside your main() function:

transaction.ts
// 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}`);

Each account has a unique address (like a bank account number) and a keypair (like your login credentials). The address is derived from the public key, while the private key is kept secret and used for signing transactions.

Fund the accounts

To perform transactions, accounts need funds. Let’s use the faucet to get some test coins:

Add this code after generating the accounts:

transaction.ts
// Fund the accounts
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`);

Run the code

Let’s test our code so far:

Terminal
npx ts-node transaction.ts

You should see output similar to:

Connected to Aptos devnet
=== Addresses ===
Alice's address: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aa
Bob's address: 0x7af2d6c93a2feafc9b69b5e8ad9d6b513b260f62f23f3a384a3a2e4a84694a9b

=== Funding accounts ===
Accounts funded successfully

=== Initial Balances ===
Alice: 100000000 octas
Bob: 0 octas

The addresses you see will be different from the ones shown here, as they are randomly generated each time.

3. Building a Transaction

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.

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

All data in Aptos transactions is serialized using Binary Canonical Serialization (BCS), a compact and deterministic format designed for blockchain use. The SDK handles this serialization for you.

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:

transaction.ts
// 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");
 
// Access transaction details from the raw transaction
const 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()}`);

The function 0x1::aptos_account::transfer is a built-in function in the Aptos framework that transfers coins between accounts. The 0x1 prefix indicates it’s part of the core framework.

4. Simulating the Transaction

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.

Simulate the transaction

Add this code after building the transaction:

transaction.ts
// 2. Simulate the transaction
console.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"}`);

Gas is the computational fee paid to process transactions on the blockchain. The total cost is calculated as gas_used Ă— gas_unit_price. Simulation helps you estimate this cost before committing to the transaction.

5. Signing and Submitting the Transaction

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.

Sign the transaction

Signing proves that Alice authorized this transaction:

Add this code after simulating the transaction:

transaction.ts
// 3. Sign the transaction
console.log("\n=== 3. Signing the transaction ===");
const senderAuthenticator = aptos.transaction.sign({
  signer: alice,
  transaction,
});
console.log("Transaction signed successfully");

Digital signatures work like a personal seal or signature in the physical world. They prove that the transaction was authorized by the account owner (who has the private key) and haven’t been tampered with.

Submit the transaction

Now we submit the signed transaction to the blockchain:

Add this code after signing the transaction:

transaction.ts
// 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}`);

The transaction hash is a unique identifier for your transaction, similar to a tracking number for a package. You can use it to check the status of your transaction on the Aptos Explorer.

6. Waiting for Confirmation

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.

Wait for transaction completion

Add this code after submitting the transaction:

transaction.ts
// 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}`);

Verify the results

Finally, let’s check the balances to confirm the transfer worked:

Add this code after waiting for the transaction:

transaction.ts
// 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)`);

Run the complete code

Now run the complete program:

Terminal
npx ts-node transaction.ts

You should see output similar to:

Connected to Aptos devnet
=== Addresses ===
Alice's address: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aa
Bob's address: 0x7af2d6c93a2feafc9b69b5e8ad9d6b513b260f62f23f3a384a3a2e4a84694a9b

=== Funding accounts ===
Accounts funded successfully

=== Initial Balances ===
Alice: 100000000 octas
Bob: 0 octas

=== 1. Building the transaction ===
Transaction built successfully
Sender: 0x978c213990c4833df71548df7ce49d54c759d6b6d932de22b24d56060b7af2aa
Sequence Number: 0
Max Gas Amount: 20000
Gas Unit Price: 100
Expiration Timestamp: 2025-03-05T22:59:21.000Z

=== 2. Simulating the transaction ===
Estimated gas units: 146
Estimated gas cost: 14600 octas
Transaction 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: SUCCESS
VM Status: Executed successfully
Gas used: 146

=== Final Balances ===
Alice: 99984400 octas (spent 15600 octas on transfer and gas)
Bob: 1000 octas (received 1000 octas)

Notice that Alice’s balance decreased by more than 1000 octas. The extra amount is the gas fee paid to process the transaction.

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.

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

Open the Aptos Explorer

Go to the Aptos Explorer.

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

Search for your transaction

Paste your transaction hash into the search bar in the middle of the page.

⚠️

Do not press enter! There is a known bug where searching with Enter does not work.

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

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

The Explorer is a powerful tool for debugging transactions and understanding blockchain activity. Developers frequently use it to verify their transactions executed as expected and to investigate any issues.

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:

These links are for the Typescript SDK but the principles are the same if you are using Python.

Explore smart contracts or account basics:

Join the Aptos Discord and share what you’re building!