Minh họa cách sử dụng WarpToSlot và SetClock để kiểm thử logic chương trình
phụ thuộc thời gian.
Thao Tác Đồng Hồ Cơ Bản
package mytestimport ("testing"litesvm "github.com/LiteSVM/litesvm-go")func TestClockWarp(t *testing.T) {svm, err := litesvm.New()if err != nil {t.Fatal(err)}defer svm.Close()// Read the initial clock.initial, err := svm.Clock()if err != nil {t.Fatal(err)}t.Logf("initial state:")t.Logf(" slot: %d", initial.Slot)t.Logf(" epoch: %d", initial.Epoch)t.Logf(" unix timestamp: %d", initial.UnixTimestamp)// Warp to slot 1_000.if err := svm.WarpToSlot(1_000); err != nil {t.Fatal(err)}after, err := svm.Clock()if err != nil {t.Fatal(err)}t.Logf("after warpToSlot(1000):")t.Logf(" slot: %d", after.Slot)t.Logf(" epoch: %d", after.Epoch)// Warp further.if err := svm.WarpToSlot(100_000); err != nil {t.Fatal(err)}after2, err := svm.Clock()if err != nil {t.Fatal(err)}t.Logf("after warpToSlot(100000):")t.Logf(" slot: %d", after2.Slot)t.Logf(" epoch: %d", after2.Epoch)}
Kiểm Thử Logic Khóa Thời Gian
package mytestimport ("encoding/binary""testing"litesvm "github.com/LiteSVM/litesvm-go"solana "github.com/gagliardetto/solana-go")func TestTimeLockedVault(t *testing.T) {svm, err := litesvm.New()if err != nil {t.Fatal(err)}defer svm.Close()// Setters are infallible in practice; discarding the return keeps the// example readable._ = svm.SetSigverify(false)_ = svm.SetBlockhashCheck(false)_ = svm.SetSysvars()// Fund a payer.priv, err := solana.NewRandomPrivateKey()if err != nil {t.Fatal(err)}payer := priv.PublicKey()if err := svm.Airdrop(payer, 10_000_000_000); err != nil {t.Fatal(err)}// Set up a time-locked vault account.// Layout: [u8 discriminator, u64 unlock_slot, u64 amount]const unlockSlot = uint64(10_000)const lockedAmount = uint64(5_000_000_000)vaultData := make([]byte, 1+8+8)vaultData[0] = 0x01binary.LittleEndian.PutUint64(vaultData[1:9], unlockSlot)binary.LittleEndian.PutUint64(vaultData[9:17], lockedAmount)programID := solana.NewWallet().PublicKey()vaultAddr := solana.NewWallet().PublicKey()minBalance, err := svm.MinimumBalanceForRentExemption(len(vaultData))if err != nil {t.Fatal(err)}acct, err := litesvm.NewAccount(minBalance+lockedAmount, vaultData, programID, false, 0)if err != nil {t.Fatal(err)}defer acct.Close()if err := svm.SetAccount(vaultAddr, acct); err != nil {t.Fatal(err)}t.Logf("vault created: unlock slot=%d, locked=%.3f SOL",unlockSlot, float64(lockedAmount)/1e9)// --- Test 1: Before unlock ---cBefore, err := svm.Clock()if err != nil {t.Fatal(err)}t.Logf("current slot: %d", cBefore.Slot)// In a real test you would build a withdraw instruction here and assert// it fails because the current slot < unlock_slot.t.Log("withdrawal attempt: EXPECTED TO FAIL (too early)")// --- Test 2: After unlock ---if err := svm.WarpToSlot(unlockSlot + 100); err != nil {t.Fatal(err)}cAfter, err := svm.Clock()if err != nil {t.Fatal(err)}t.Logf("current slot: %d", cAfter.Slot)// Build and submit the withdraw instruction; assert it succeeds.t.Log("withdrawal attempt: EXPECTED TO SUCCEED (after unlock)")// Verify vault state.updated := svm.GetAccount(vaultAddr)if updated == nil {t.Fatal("vault missing")}defer updated.Close()t.Logf("vault balance: %d lamports", updated.Lamports())_ = payer // payer would be referenced when building the withdraw ix}
Đọc Lịch Epoch
func TestReadEpochSchedule(t *testing.T) {svm, err := litesvm.New()if err != nil {t.Fatal(err)}defer svm.Close()es, err := svm.EpochSchedule()if err != nil {t.Fatal(err)}t.Logf("slots per epoch: %d", es.SlotsPerEpoch)t.Logf("first normal epoch: %d", es.FirstNormalEpoch)t.Logf("first normal slot: %d", es.FirstNormalSlot)}
WarpToSlot tiến đồng hồ ở trường Slot nhưng không tự động
cập nhật Epoch hay UnixTimestamp. Dùng SetClock để kiểm soát toàn bộ các
trường đồng hồ.
Thao Tác Đồng Hồ Thủ Công
Khi chương trình của bạn đọc Epoch hoặc UnixTimestamp từ sysvar Clock, hãy
thiết lập trực tiếp các trường đó bằng SetClock:
func TestSetClock(t *testing.T) {svm, err := litesvm.New()if err != nil {t.Fatal(err)}defer svm.Close()c, err := svm.Clock()if err != nil {t.Fatal(err)}c.Slot = 50_000c.Epoch = 5c.UnixTimestamp = 1_700_000_000if err := svm.SetClock(c); err != nil {t.Fatal(err)}after, err := svm.Clock()if err != nil {t.Fatal(err)}t.Logf("slot: %d", after.Slot) // 50000t.Logf("epoch: %d", after.Epoch) // 5t.Logf("unix: %d", after.UnixTimestamp) // 1700000000}
Điều này phản ánh mẫu set_sysvar(&clock) trong Rust. Dùng WarpToSlot để tiến
slot đơn giản, dùng SetClock khi bạn cần kiểm soát epoch hoặc timestamp.
Các Trường Hợp Sử Dụng
Thao tác thời gian hữu ích để kiểm thử:
| Kịch bản | Cách tiếp cận |
|---|---|
| Vesting token | Warp qua ngưỡng / mốc vesting |
| Kết thúc phiên đấu giá | Warp qua slot kết thúc đấu giá |
| Phần thưởng staking | Dùng SetClock để đặt epoch |
| Rút tiền khóa thời gian | Warp qua slot mở khóa |
| Giới hạn tốc độ | Warp giữa các khoảng thời gian được phép |
| Lệnh hết hạn | Warp qua thời điểm hết hạn lệnh |
WarpToSlot chỉ thay đổi slot. Unix timestamp có thể không cập nhật
tương ứng - dùng SetClock nếu chương trình của bạn đọc UnixTimestamp.
Những Điểm Chính
- Sysvars mặc định đã bật -
litesvm.New()trả về một handle với sysvars đã được khởi tạo; gọiSetSysvars()để đặt lại về mặc định nếu bạn đã thay đổi chúng. - Tiến về phía trước -
WarpToSlot(slot)chỉ tiến trường slot. - Kiểm soát toàn bộ -
SetClock(Clock{...})cho phép bạn đặtEpoch,UnixTimestampvà các trường khác. - Đọc -
svm.Clock()đọc các giá trị hiện tại. - Mẫu kiểm thử - kiểm thử trước và sau ranh giới thời gian; kỳ vọng thất bại ở một phía và thành công ở phía kia.
Is this page helpful?