Путешествие во времени

Среда выполнения Surfpool предоставляет три вспомогательных метода для путешествия во времени. Каждый из них перемещает локальные часы к абсолютной цели (не к относительному смещению) и возвращает обновлённый EpochInfo, чтобы тесты могли убедиться, что среда выполнения действительно достигла запрошенного момента времени.

Вспомогательный методЦельВозвращает
time_travel_to_slot / timeTravelToSlotАбсолютный номер slotEpochInfo с новым absolute_slot
time_travel_to_epoch / timeTravelToEpochАбсолютный номер epochEpochInfo с новым epoch
time_travel_to_timestamp / timeTravelToTimestampUnix-временная метка в миллисекундахEpochInfo, отражающий вычисленный slot

Только вперёд

Путешествие во времени может перемещать часы только вперёд. Вызов этих методов с целевым значением в прошлом является холостой операцией — вспомогательный метод возвращает текущий EpochInfo без изменений.

Переход к 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);

Переход к epoch

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

Переход к Unix-временной метке

Передавайте временную метку в миллисекундах, а не в секундах. Среда выполнения вычисляет ближайший slot для этой временной метки.

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

Типичные сценарии использования

Тест блокировки или окна вестинга

Приведённый ниже пример является наброском — assertWithdrawFails и assertWithdrawSucceeds являются заполнителями для любых вспомогательных методов на стороне клиента, которые ваш набор тестов использует для проверки поведения 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();

Сценарий с несколькими epoch

Промежуточные slot пропускаются

Перемещение во времени выполняется напрямую к цели — переход с epoch 1 на epoch 5 пропускает slot между ними. Если вашей программе необходимо, чтобы каждая промежуточная граница epoch срабатывала (например, для начисления наград за epoch), вызывайте time_travel_to_epoch один раз за epoch с необходимыми транзакциями между вызовами.

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

Структура EpochInfo

Оба SDK возвращают объект типа EpochInfo со следующими полями:

ПолеRustJS
Абсолютный slotabsolute_slot: u64absoluteSlot: number
slot внутри epochslot_index: u64slotIndex: number
slot в epochslots_in_epoch: u64slotsInEpoch: number
Номер epochepoch: u64epoch: number
Высота блокаblock_height: u64blockHeight: number
Число транзакцийtransaction_count: Option<u64>transactionCount?: number

Is this page helpful?