Dokumentacja SolanaLiteSVMTypeScriptPrzykłady

Testowanie oparte na czasie

Demonstruje użycie warpToSlot do testowania logiki programu zależnej od czasu.

Podstawowa manipulacja zegarem

import { createClient, generateKeyPairSigner } from "@solana/kit";
import { litesvm } from "@solana/kit-plugin-litesvm";
import { signer } from "@solana/kit-plugin-signer";
const mySigner = await generateKeyPairSigner();
const client = createClient().use(signer(mySigner)).use(litesvm());
// Enable sysvars for clock access
client.svm.withSysvars();
// Check initial clock
const initialClock = client.svm.getClock();
console.log("Initial state:");
console.log(" Slot:", initialClock.slot);
console.log(" Epoch:", initialClock.epoch);
console.log(" Unix timestamp:", initialClock.unixTimestamp);
// Warp to slot 1000
client.svm.warpToSlot(1000n);
const afterWarp = client.svm.getClock();
console.log("\nAfter warpToSlot(1000):");
console.log(" Slot:", afterWarp.slot);
console.log(" Epoch:", afterWarp.epoch);
// Warp further
client.svm.warpToSlot(100000n);
const afterWarp2 = client.svm.getClock();
console.log("\nAfter warpToSlot(100000):");
console.log(" Slot:", afterWarp2.slot);
console.log(" Epoch:", afterWarp2.epoch);

Testowanie logiki zablokowanej czasowo

Przykładowy wzorzec testowania funkcjonalności zablokowanej czasowo:

import {
createClient,
address,
generateKeyPairSigner,
lamports
} from "@solana/kit";
import { litesvm } from "@solana/kit-plugin-litesvm";
import { signer } from "@solana/kit-plugin-signer";
const mySigner = await generateKeyPairSigner();
const client = createClient().use(signer(mySigner)).use(litesvm());
client.svm.withSigverify(false).withBlockhashCheck(false).withSysvars();
// Fund payer
client.svm.airdrop(client.payer.address, lamports(10_000_000_000n));
// Set up a time-locked vault account
// Structure: [u8 discriminator, u64 unlock_slot, u64 amount]
const unlockSlot = 10000n;
const lockedAmount = 5_000_000_000n;
const vaultData = new Uint8Array(1 + 8 + 8);
const view = new DataView(vaultData.buffer);
vaultData[0] = 0x01; // discriminator
view.setBigUint64(1, unlockSlot, true); // unlock_slot
view.setBigUint64(9, lockedAmount, true); // amount
const programId = address("TimeLockedVault11111111111111111111111"); // replace or generateKeyPairSigner()
const vaultAddress = address("Vault111111111111111111111111111"); // replace or generateKeyPairSigner()
const minBalance = client.svm.minimumBalanceForRentExemption(
BigInt(vaultData.length)
);
client.svm.setAccount({
address: vaultAddress,
data: vaultData,
executable: false,
lamports: lamports(minBalance + lockedAmount),
programAddress: programId,
space: BigInt(vaultData.length)
});
console.log("Vault created with unlock slot:", unlockSlot);
console.log("Locked amount:", Number(lockedAmount) / 1e9, "SOL");
// Test 1: Try to withdraw before unlock (should fail)
console.log("\n--- Test 1: Before unlock ---");
const currentClock = client.svm.getClock();
console.log("Current slot:", currentClock.slot);
// In a real test, you would:
// 1. Build a withdraw instruction
// 2. Send it and expect it to fail
console.log("Withdrawal attempt: EXPECTED TO FAIL (too early)");
// Test 2: Warp to after unlock slot
console.log("\n--- Test 2: After unlock ---");
client.svm.warpToSlot(unlockSlot + 100n);
const newClock = client.svm.getClock();
console.log("Current slot:", newClock.slot);
// In a real test:
// 1. Build a withdraw instruction
// 2. Send it and expect it to succeed
console.log("Withdrawal attempt: EXPECTED TO SUCCEED (after unlock)");
// Verify vault state
const updatedVault = client.svm.getAccount(vaultAddress);
if (updatedVault.exists) {
console.log("\nVault balance:", updatedVault.lamports);
}

Odczytywanie harmonogramu epoch

Możesz odczytać harmonogram epoch, aby zrozumieć relację slot/epoch w klastrze:

import { createClient, generateKeyPairSigner } from "@solana/kit";
import { litesvm } from "@solana/kit-plugin-litesvm";
import { signer } from "@solana/kit-plugin-signer";
const mySigner = await generateKeyPairSigner();
const client = createClient().use(signer(mySigner)).use(litesvm());
client.svm.withSysvars();
const epochSchedule = client.svm.getEpochSchedule();
console.log("Slots per epoch:", epochSchedule.slotsPerEpoch);
console.log("First normal epoch:", epochSchedule.firstNormalEpoch);
console.log("First normal slot:", epochSchedule.firstNormalSlot);

warpToSlot przesuwa pole slot zegara, ale nie aktualizuje automatycznie pola epoch ani unixTimestamp. Użyj setClock, aby mieć pełną kontrolę nad polami zegara.

Ręczna manipulacja zegarem

Gdy Twój program odczytuje epoch lub unix_timestamp z sysvaru Clock, użyj setClock, aby ustawić te pola bezpośrednio:

import { createClient, generateKeyPairSigner } from "@solana/kit";
import { litesvm } from "@solana/kit-plugin-litesvm";
import { signer } from "@solana/kit-plugin-signer";
const mySigner = await generateKeyPairSigner();
const client = createClient().use(signer(mySigner)).use(litesvm());
client.svm.withSysvars();
// Get clock, mutate, write back
const clock = client.svm.getClock();
clock.slot = 50000n;
clock.epoch = 5n;
clock.unixTimestamp = 1700000000n;
client.svm.setClock(clock);
const after = client.svm.getClock();
console.log("Slot:", after.slot); // 50000n
console.log("Epoch:", after.epoch); // 5n
console.log("Timestamp:", after.unixTimestamp); // 1700000000n

To odzwierciedla wzorzec Rust set_sysvar(&clock). Używaj warpToSlot do prostego przesuwania slot, a setClock gdy potrzebujesz kontroli nad epoch lub znacznikiem czasu.

Przypadki użycia

Manipulacja czasem jest przydatna do testowania:

ScenariuszPodejście
Nabywanie tokenów (vesting)Przesuń poza próg/kamienie milowe vestingu
Zakończenia aukcjiPrzesuń poza slot zakończenia aukcji
Nagrody za stakowanieUżyj setClock, aby ustawić epoch
Wypłaty zablokowane czasowoPrzesuń poza slot odblokowania
Ograniczanie częstotliwościPrzesuń między dozwolonymi interwałami
Wygasające zleceniaPrzesuń poza datę wygaśnięcia zlecenia

Pamiętaj, że warpToSlot zmienia tylko slot. Znacznik czasu unix może nie aktualizować się proporcjonalnie w zależności od implementacji SVM.

Kluczowe informacje

  1. Włącz Sysvary: Wywołaj withSysvars() przed użyciem metod zegara
  2. Przesuwanie do przodu: Użyj warpToSlot(slot), aby przesunąć slot
  3. Pełna kontrola: Użyj setClock, gdy chcesz ustawić epoch, unixTimestamp lub inne pola zegara
  4. Odczyt zegara: Użyj getClock(), aby odczytać bieżący slot, epoch i znacznik czasu
  5. Wzorzec testowania: Testuj przed i po granicach czasowych

Is this page helpful?

Spis treści

Edytuj stronę