وثائق سولاناLiteSVMTypeScriptأمثلة

الاختبار المبني على الوقت

يوضح كيفية استخدام warpToSlot لاختبار منطق البرنامج المعتمد على الوقت.

التحكم الأساسي في الساعة

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

اختبار المنطق المقيّد بالوقت

نمط مثالي لاختبار الوظائف المقيّدة بالوقت:

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);
}

قراءة جدول الـ epoch

يمكنك قراءة جدول الـ epoch لفهم العلاقة بين الـ slot والـ epoch على الشبكة:

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 يُقدّم حقل slot في الساعة لكنه لا يُحدّث epoch أو unixTimestamp تلقائيًا. استخدم setClock للتحكم الكامل في حقول الساعة.

التحكم اليدوي في الساعة

عندما يقرأ برنامجك epoch أو unix_timestamp من متغير النظام Clock، استخدم setClock لتعيين تلك الحقول مباشرةً:

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

يُحاكي هذا نمط set_sysvar(&clock) في Rust. استخدم warpToSlot للتقدم البسيط في الـ slot، وsetClock عندما تحتاج إلى التحكم في الـ epoch أو الطابع الزمني.

حالات الاستخدام

التحكم في الوقت مفيد لاختبار:

السيناريوالنهج
إيداع الرموز المؤجّلالتقدم إلى ما بعد نقاط التخصيص
نهايات المزاداتالتقدم إلى ما بعد الـ slot النهائي للمزاد
مكافآت التخزيناستخدم setClock لتعيين الـ epoch
عمليات السحب المقيّدة بالوقتالتقدم إلى ما بعد الـ slot الخاص بالإلغاء
تحديد معدل الاستخدامالتقدم بين الفترات المسموح بها
الأوامر منتهية الصلاحيةالتقدم إلى ما بعد انتهاء صلاحية الأمر

تذكر أن warpToSlot يُغيّر الـ slot فقط. قد لا يتحدث الطابع الزمني Unix بشكل متناسب اعتمادًا على تطبيق SVM.

النقاط الرئيسية

  1. تفعيل متغيرات النظام: استدعِ withSysvars() قبل استخدام أساليب الساعة
  2. التقدم للأمام: استخدم warpToSlot(slot) للتقدم في الـ slot
  3. التحكم الكامل: استخدم setClock عندما تحتاج إلى تعيين epoch أو unixTimestamp أو حقول الساعة الأخرى
  4. قراءة الساعة: استخدم getClock() لقراءة الـ slot والـ epoch والطابع الزمني الحاليين
  5. نمط الاختبار: اختبر قبل حدود الوقت وبعدها

Is this page helpful?

جدول المحتويات

تعديل الصفحة