Perjalanan Waktu

Runtime Surfpool menyediakan tiga helper perjalanan waktu. Masing-masing memindahkan jam lokal ke target absolut (bukan offset relatif) dan mengembalikan EpochInfo yang telah diperbarui sehingga pengujian dapat memverifikasi bahwa runtime benar-benar mencapai waktu yang diminta.

HelperTargetMengembalikan
time_travel_to_slot / timeTravelToSlotNomor slot absolutEpochInfo dengan absolute_slot baru
time_travel_to_epoch / timeTravelToEpochNomor epoch absolutEpochInfo dengan epoch baru
time_travel_to_timestamp / timeTravelToTimestampStempel waktu Unix dalam milidetikEpochInfo yang mencerminkan slot yang tersirat

Hanya maju

Time travel hanya dapat memajukan jam ke depan. Target yang berada di masa lalu akan ditolak, bukan diabaikan — helper Rust mengembalikan Err dan helper JS akan melempar pengecualian. Pesan kesalahan menyebutkan unit mana yang mundur ke belakang, misalnya Cannot travel to past slot: target=1000, current=2000.

Lompat Ke Slot

use surfpool_sdk::Surfnet;
let surfnet = Surfnet::start().await?;
let cheats = surfnet.cheatcodes();
let info = cheats.time_travel_to_slot(1_000_000)?;
assert!(info.absolute_slot >= 1_000_000);

Lompat Ke Epoch

let info = cheats.time_travel_to_epoch(420)?;
assert_eq!(info.epoch, 420);

Lompat Ke Stempel Waktu Unix

Berikan stempel waktu dalam milidetik sejak Unix epoch — satuan yang sama dengan Date.now() JavaScript — bukan detik. Runtime akan menghitung slot terdekat pada stempel waktu tersebut.

// 2030-01-01T00:00:00Z
let info = cheats.time_travel_to_timestamp(1_893_456_000_000)?;

Jam melaporkan dalam detik, bukan milidetik

Setiap stempel waktu yang Anda baca kembali dari runtime berada dalam detikunix_timestamp dari sysvar Clock on-chain, dan ClockValue yang dibawa oleh event systemClockUpdated. Memasukkan salah satu nilai tersebut langsung ke dalam helper time travel akan mengarah ke momen di awal tahun 1970, sehingga panggilan tersebut ditolak sebagai target masa lalu. Kalikan dengan 1000 terlebih dahulu.

// WRONG — `unixTimestamp` is in seconds, so this is a past target.
surfnet.timeTravelToTimestamp(clock.unixTimestamp + 3600);
// RIGHT — convert to milliseconds.
surfnet.timeTravelToTimestamp((clock.unixTimestamp + 3600) * 1000);

Jeda dan Lanjutkan Jam

Time travel melompat ke target; menjeda menghentikan jam agar tidak maju sama sekali. surfnet_pauseClock menghentikan produksi slot dan perkembangan waktu hingga surfnet_resumeClock dijalankan — gunakan ini ketika pengujian membutuhkan slot dan stempel waktu tetap diam selama beberapa asersi.

Baik Rust SDK maupun kelas Surfnet di @solana/surfpool tidak membungkus kedua cheatcode ini. Panggil melalui plugin Kit, atau langsung melalui JSON-RPC.

const paused = await client.cheatcodes.pauseClock().send();
// Nothing advances until the clock is resumed, so this is the only thing that
// moves the slot.
await client.cheatcodes
.timeTravel({ absoluteSlot: paused.absoluteSlot + 1_000n })
.send();
await client.cheatcodes.resumeClock().send();

Kedua cheatcode mengembalikan EpochInfo — status jam pada saat dijeda, dan setelah dilanjutkan. Perhatikan dua hal yang tidak dibawa oleh bentuk tersebut:

  • Tidak ada stempel waktu. EpochInfo tidak memiliki field waktu. Baca waktu Unix yang disimulasikan dari sysvar Clock: getAccountInfo pada SysvarC1ock11111111111111111111111111111111 dengan encoding jsonParsed — sekali lagi, dalam detik.
  • Tidak ada flag jeda. Tidak ada metode RPC yang melaporkan apakah jam sedang dijeda. Dari SDK, pantau event clockUpdate, yang dipicu dengan clockCommand setiap kali perintah jeda, lanjutkan, atau perubahan interval dijalankan. Jika tidak, lacak statusnya dalam pengujian Anda.

Pola Umum

Uji Lockup atau Jendela Vesting

Contoh di bawah ini hanyalah sketsa — assertWithdrawFails dan assertWithdrawSucceeds adalah placeholder untuk helper sisi klien apa pun yang digunakan layanan pengujian Anda untuk memverifikasi perilaku RPC.

import { Surfnet } from "@solana/surfpool";
const surfnet = Surfnet.start();
const beneficiary = Surfnet.newKeypair();
// 1. Set up a vesting account that unlocks at slot 1,000,000.
surfnet.setAccount(/* ...lockup program state... */);
// 2. Verify withdrawal fails before unlock.
await assertWithdrawFails(surfnet.rpcUrl, beneficiary);
// 3. Travel past the unlock slot.
surfnet.timeTravelToSlot(1_000_001);
// 4. Verify withdrawal succeeds.
await assertWithdrawSucceeds(surfnet.rpcUrl, beneficiary);
surfnet.stop();

Jalankan Skenario Multi-Epoch

Slot perantara dilewati

Perjalanan waktu langsung melompat ke target — berpindah dari epoch 1 ke epoch 5 akan melewati slot-slot di antaranya. Jika program Anda membutuhkan setiap batas epoch perantara untuk dieksekusi (misalnya, untuk mengkredit hadiah per-epoch), panggil time_travel_to_epoch sekali per epoch dengan transaksi yang diperlukan di antaranya.

for epoch in 2..=5 {
cheats.time_travel_to_epoch(epoch)?;
surfnet.rpc_client().send_transaction(&claim_rewards_tx)?;
}

Bentuk EpochInfo

Kedua SDK mengembalikan objek berbentuk EpochInfo dengan field-field berikut:

FieldRustJS
Slot absolutabsolute_slot: u64absoluteSlot: number
Slot dalam epochslot_index: u64slotIndex: number
Slot per epochslots_in_epoch: u64slotsInEpoch: number
Nomor epochepoch: u64epoch: number
Tinggi blokblock_height: u64blockHeight: number
Jumlah transaksitransaction_count: Option<u64>transactionCount?: number

Is this page helpful?

Daftar Isi

Edit Halaman
© 2026 Yayasan Solana. Semua hak dilindungi.