Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,47 @@ All notable changes to this repository are documented here.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [2026-10-08] - Anchor v1 tests send v1 transactions

Solana's v1 transaction format (SIMD-0385) activated on mainnet beta at epoch 1035
(15 September 2026). It raises the transaction size limit from 1,232 to 4,096 bytes
and moves the compute budget out of ComputeBudget instructions and into the message.
Programs need no change for it; the client that builds the transaction does.

### Changed

- Every Anchor v1 example's tests send v1 transactions, through `solana-kite` 0.6.0,
whose senders and token, Token Extensions and transfer hook helpers all build v1.
The manifests move from kite 0.5.0 to 0.6.0.
- A v1 transaction's unset limits are zero, not the legacy defaults, so kite 0.6
sets the compute unit and loaded-accounts data size limits in every transaction it
builds. Its senders and helpers take a new last argument,
`compute_unit_limit: Option<u32>`, and every call here passes `None`: kite
simulates the transaction and sends it with the compute units the simulation used.
- The six tests that build a transaction themselves (to read logs, measure compute
units or read a program error code) build it with kite's
`build_transaction_from_instructions` and `get_transaction_config`, with
`MAX_COMPUTE_UNIT_LIMIT` from `solana-compute-budget`, and send it through LiteSVM.
The three compression examples add kite for this, and turn on `no-entrypoint` for
kite's `spl-token` and `spl-associated-token-account`, whose program entrypoints
otherwise clash with the example program's when the test binary links. They,
`hello-solana`, `options`
and `order-book` no longer use `solana-message` or `solana-transaction` directly,
and drop them from their manifests.

### Added

- `basics/transaction-v1/anchor-v1`: a program that stores a 3,000 byte document in
one instruction, which only fits in a v1 transaction. Its tests measure the
transaction against both size limits, set each config field themselves, and show
that an unset field means zero rather than the default.

### Note

- Anchor v2 and Quasar tests still send legacy transactions: `anchor-v2-testing`
pins LiteSVM 0.13.1 and `quasar-svm` is on a `solana-message` without the `v1`
module. Both predate v1.

## [2026-10-04] - Escrow: the taker signs the terms

### Fixed
Expand Down
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ Run an example's tests with the command for its framework, from the framework di

- **Anchor v2** (in `anchor/`): `anchor test` (runs `cargo test`, per the `[scripts]` table in `Anchor.toml`), with the v2 CLI: `cargo install anchor-cli --version 2.0.0-rc.1 --locked`.
- **Anchor v1** (in `anchor-v1/`): the same `anchor test`, with the v1 CLI: `avm install 1.2.0 && avm use 1.2.0`. Selecting the wrong CLI is the usual cause of a confusing build failure in these directories.
Anchor v1 tests send v1 transactions (4,096 bytes, resource limits in the message) through
`solana-kite` 0.6. Its senders take a last `compute_unit_limit: Option<u32>`: pass `None` and kite
simulates the transaction and sends it with the compute units the simulation used. A test that needs the
transaction's metadata (logs, compute units, a program error code) builds it with kite's
`build_transaction_from_instructions` and sends it through LiteSVM itself. Kite rejects ComputeBudget
instructions, which do nothing in a v1 transaction.
- **Quasar:** `quasar test`.
- **Native / Pinocchio:** `cargo test --manifest-path=./program/Cargo.toml` (build first with `cargo build-sbf --manifest-path=./program/Cargo.toml`).

Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ Send SOL between two accounts.

[⚓ Anchor v1](./basics/transfer-sol/anchor-v1) [⚓ Anchor v2](./basics/transfer-sol/anchor) [💫 Quasar](./basics/transfer-sol/quasar) [🤥 Pinocchio](./basics/transfer-sol/pinocchio) [🦀 Native](./basics/transfer-sol/native) [🧬 ASM](./basics/transfer-sol/asm)

### Transaction v1

Store a 3,000 byte document in one instruction using Solana's v1 transaction format, live on mainnet since September 2026: 4,096 bytes instead of 1,232, and a transaction config in the message in place of ComputeBudget instructions. The program needs no change for v1; the LiteSVM tests are what build the v1 transactions, and they show the config fields one by one.

[⚓ Anchor v1](./basics/transaction-v1/anchor-v1)

### Pyth Price Feeds

An **oracle** brings real-world market prices - a dollar, a stock, a token - [onchain](https://solana.com/docs/terminology#onchain), like a Bloomberg terminal feeding live quotes. [Pyth](https://pyth.network/) publishes low-latency prices from institutional sources, each in its own price feed account. This example reads a feed and logs its price, confidence interval, and exponent - the building block an AMM, lending market, or vault uses to value assets.
Expand Down Expand Up @@ -413,6 +419,10 @@ Yes. "Program" is Solana's term for what other chains call a smart contract: cod

Start with the [escrow example](./finance/escrow/anchor/), the best first finance program to learn: one state PDA, one vault, and three instruction handlers that swap two tokens atomically. There is also a [30-minute video walkthrough](https://www.youtube.com/watch?v=B5eBWWQfQuM) building it from scratch.

### Do these examples work with Solana transaction v1?

Yes. The v1 format (4,096 byte transactions, live on mainnet since epoch 1035 on 15 September 2026) changes how a client builds a transaction, not what a program sees, so every program here can be called through v1 as is. Every Anchor v1 example's tests send their transactions as v1, through [solana-kite](https://crates.io/crates/solana-kite) 0.6, and the [transaction v1 example](./basics/transaction-v1/anchor-v1/) shows the config fields that replace ComputeBudget instructions. The Anchor v2 and Quasar tests still send legacy transactions, because their test harnesses run on virtual machines that predate v1.

### How do I test a Solana program without running a validator?

Use [LiteSVM](https://www.anchor-lang.com/docs/testing/litesvm): Rust integration tests that run the program in-process, orders of magnitude faster than `solana-test-validator`. Every example in this repository tests this way, and `anchor init` scaffolds it by default since Anchor 1.0.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ litesvm = "0.16.0"
solana-signer = "3.0.0"
solana-keypair = "3.0.1"
borsh = "1.6.1"
solana-kite = "0.5.0"
solana-kite = "0.6.0"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ fn test_create_address_info() {
vec![instruction],
&[&payer, &address_info_keypair],
&payer.pubkey(),
None,
)
.unwrap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ litesvm = "0.16.0"
solana-signer = "3.0.0"
solana-keypair = "3.0.1"
borsh = "1.6.1"
solana-kite = "0.5.0"
solana-kite = "0.6.0"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ fn test_check_accounts() {
vec![create_account_ix],
&[&payer, &account_to_change],
&payer.pubkey(),
None,
)
.unwrap();

Expand All @@ -56,6 +57,7 @@ fn test_check_accounts() {
vec![check_accounts_ix],
&[&payer],
&payer.pubkey(),
None,
)
.unwrap();
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ anchor-lang = "1.2.0"
litesvm = "0.16.0"
solana-signer = "3.0.0"
solana-keypair = "3.0.1"
solana-kite = "0.5.0"
solana-kite = "0.6.0"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn test_create_and_close_user() {
}
.to_account_metas(None),
);
send_transaction_from_instructions(&mut svm, vec![create_ix], &[&payer], &payer.pubkey())
send_transaction_from_instructions(&mut svm, vec![create_ix], &[&payer], &payer.pubkey(), None)
.unwrap();

// Verify account exists and has correct data
Expand All @@ -62,7 +62,7 @@ fn test_create_and_close_user() {
}
.to_account_metas(None),
);
send_transaction_from_instructions(&mut svm, vec![close_ix], &[&payer], &payer.pubkey())
send_transaction_from_instructions(&mut svm, vec![close_ix], &[&payer], &payer.pubkey(), None)
.unwrap();

// Verify account is closed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ litesvm = "0.16.0"
solana-signer = "3.0.0"
solana-keypair = "3.0.1"
borsh = "1.6.1"
solana-kite = "0.5.0"
solana-kite = "0.6.0"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ fn test_initialize_counter() {
vec![instruction],
&[&payer, &counter_keypair],
&payer.pubkey(),
None,
)
.unwrap();

Expand Down Expand Up @@ -81,6 +82,7 @@ fn test_increment_counter() {
vec![init_ix],
&[&payer, &counter_keypair],
&payer.pubkey(),
None,
)
.unwrap();

Expand All @@ -93,7 +95,8 @@ fn test_increment_counter() {
}
.to_account_metas(None),
);
send_transaction_from_instructions(&mut svm, vec![inc_ix], &[&payer], &payer.pubkey()).unwrap();
send_transaction_from_instructions(&mut svm, vec![inc_ix], &[&payer], &payer.pubkey(), None)
.unwrap();

let count = fetch_counter(&svm, &counter_keypair.pubkey());
assert_eq!(count, 1, "Expected count to be 1");
Expand All @@ -120,6 +123,7 @@ fn test_increment_counter_again() {
vec![init_ix],
&[&payer, &counter_keypair],
&payer.pubkey(),
None,
)
.unwrap();

Expand All @@ -133,8 +137,14 @@ fn test_increment_counter_again() {
}
.to_account_metas(None),
);
send_transaction_from_instructions(&mut svm, vec![inc_ix], &[&payer], &payer.pubkey())
.unwrap();
send_transaction_from_instructions(
&mut svm,
vec![inc_ix],
&[&payer],
&payer.pubkey(),
None,
)
.unwrap();
svm.expire_blockhash();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ anchor-lang = "1.2.0"
litesvm = "0.16.0"
solana-signer = "3.0.0"
solana-keypair = "3.0.1"
solana-kite = "0.5.0"
solana-kite = "0.6.0"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ fn test_create_the_account() {
vec![instruction],
&[&payer, &new_account],
&payer.pubkey(),
None,
)
.unwrap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ anchor-lang = "1.2.0"
litesvm = "0.16.0"
solana-signer = "3.0.0"
solana-keypair = "3.0.1"
solana-kite = "0.5.0"
solana-kite = "0.6.0"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ fn test_pull_lever_cpi() {
vec![init_ix],
&[&payer, &power_keypair],
&payer.pubkey(),
None,
)
.unwrap();

Expand All @@ -96,7 +97,7 @@ fn test_pull_lever_cpi() {
}
.to_account_metas(None),
);
send_transaction_from_instructions(&mut svm, vec![pull_ix], &[&payer], &payer.pubkey())
send_transaction_from_instructions(&mut svm, vec![pull_ix], &[&payer], &payer.pubkey(), None)
.unwrap();

// Verify power is now on
Expand All @@ -119,7 +120,7 @@ fn test_pull_lever_cpi() {
}
.to_account_metas(None),
);
send_transaction_from_instructions(&mut svm, vec![pull_ix2], &[&payer], &payer.pubkey())
send_transaction_from_instructions(&mut svm, vec![pull_ix2], &[&payer], &payer.pubkey(), None)
.unwrap();

// Verify power is now off again
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ anchor-lang = "1.2.0"
litesvm = "0.16.0"
solana-signer = "3.0.0"
solana-keypair = "3.0.1"
solana-kite = "0.5.0"
solana-kite = "0.6.0"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ fn test_initialize_lever() {
vec![instruction],
&[&payer, &power_keypair],
&payer.pubkey(),
None,
)
.unwrap();

Expand Down Expand Up @@ -77,6 +78,7 @@ fn test_switch_power() {
vec![init_ix],
&[&payer, &power_keypair],
&payer.pubkey(),
None,
)
.unwrap();

Expand All @@ -93,7 +95,7 @@ fn test_switch_power() {
.to_account_metas(None),
);
svm.expire_blockhash();
send_transaction_from_instructions(&mut svm, vec![switch_ix], &[&payer], &payer.pubkey())
send_transaction_from_instructions(&mut svm, vec![switch_ix], &[&payer], &payer.pubkey(), None)
.unwrap();

assert!(
Expand All @@ -114,8 +116,14 @@ fn test_switch_power() {
.to_account_metas(None),
);
svm.expire_blockhash();
send_transaction_from_instructions(&mut svm, vec![switch_ix2], &[&payer], &payer.pubkey())
.unwrap();
send_transaction_from_instructions(
&mut svm,
vec![switch_ix2],
&[&payer],
&payer.pubkey(),
None,
)
.unwrap();

assert!(
!read_power_is_on(&svm, &power_keypair.pubkey()),
Expand Down
2 changes: 1 addition & 1 deletion basics/favorites/anchor-v1/programs/favorites/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ anchor-lang = {version = "1.2.0", features = ["init-if-needed"]}
litesvm = "0.16.0"
solana-signer = "3.0.0"
solana-keypair = "3.0.1"
solana-kite = "0.5.0"
solana-kite = "0.6.0"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,14 @@ fn test_set_favorites() {
.to_account_metas(None),
);

send_transaction_from_instructions(&mut svm, vec![instruction], &[&payer], &payer.pubkey())
.unwrap();
send_transaction_from_instructions(
&mut svm,
vec![instruction],
&[&payer],
&payer.pubkey(),
None,
)
.unwrap();

let data = read_favorites(&svm, &pda);
assert_eq!(data.number, 23);
Expand Down Expand Up @@ -123,8 +129,14 @@ fn test_update_favorites() {
}
.to_account_metas(None),
);
send_transaction_from_instructions(&mut svm, vec![instruction], &[&payer], &payer.pubkey())
.unwrap();
send_transaction_from_instructions(
&mut svm,
vec![instruction],
&[&payer],
&payer.pubkey(),
None,
)
.unwrap();

// Update favorites with new hobbies
svm.expire_blockhash();
Expand All @@ -148,7 +160,7 @@ fn test_update_favorites() {
}
.to_account_metas(None),
);
send_transaction_from_instructions(&mut svm, vec![update_ix], &[&payer], &payer.pubkey())
send_transaction_from_instructions(&mut svm, vec![update_ix], &[&payer], &payer.pubkey(), None)
.unwrap();

let data = read_favorites(&svm, &pda);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ anchor-lang = "1.2.0"
[dev-dependencies]
litesvm = "0.16.0"
solana-signer = "3.0.0"
solana-kite = "0.5.0"
solana-transaction = "4.1.5"
solana-kite = "0.6.0"
# The named limit for the one transaction the test builds itself. Same version
# solana-kite 0.6 builds against.
solana-compute-budget = "4.2"

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("solana"))'] }
Loading
Loading